How to find/replace and increment a matched number with sed/awk?
Solution 1:
I think finding file isn't the difficult part for you. I therefore just go to the point, to do the +1 calculation. If you have gnu sed, it could be done in this way:
sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge' file
let's take an example:
kent$ cat test
ello
barbaz?cache_version=3fooooo
bye
kent$ sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge' test
ello
barbaz?cache_version=4fooooo
bye
you could add -i option if you like.
edit
/e
allows you to pass matched part to external command, and do substitution with the execution result. Gnu sed only.
see this example: external command/tool echo
, bc
are used
kent$ echo "result:3*3"|sed -r 's/(result:)(.*)/echo \1$(echo "\2"\|bc)/ge'
gives output:
result:9
you could use other powerful external command, like cut, sed (again), awk...
Solution 2:
This perl
command will search all files in current directory (without traverse it, you will need File::Find
module or similar for that more complex task) and will increment the number of a line that matches cache_version=
. It uses the /e
flag of the regular expression that evaluates the replacement part.
perl -i.bak -lpe 'BEGIN { sub inc { my ($num) = @_; ++$num } } s/(cache_version=)(\d+)/$1 . (inc($2))/eg' *
I tested it with file
in current directory with following data:
hello
cache_version=3
bye
It backups original file (ls -1
):
file
file.bak
And file
now with:
hello
cache_version=4
bye
I hope it can be useful for what you are looking for.
UPDATE to use File::Find
for traversing directories. It accepts *
as argument but will discard them with those found with File::Find
. The directory to begin the search is the current of execution of the script. It is hardcoded in the line find( \&wanted, "." )
.
perl -MFile::Find -i.bak -lpe '
BEGIN {
sub inc {
my ($num) = @_;
++$num
}
sub wanted {
if ( -f && ! -l ) {
push @ARGV, $File::Find::name;
}
}
@ARGV = ();
find( \&wanted, "." );
}
s/(cache_version=)(\d+)/$1 . (inc($2))/eg
' *