VIM: match number following PATTERN, replace with number + 1 - regex

I have a set of lines that look like:
$AERDIR/aergen.sh -n control -s 2100 -e 2120 -m 3 -a -x -z 144 -p -g
$AERDIR/aergen.sh -n Cl26E10 -s 2100 -e 2120 -m 3 -a -x -c 2.6E-10 -z 145 -p -g
$AERDIR/aergen.sh -n Br26E12 -s 2100 -e 2120 -m 3 -a -x -b 2.6E-12 -z 146 -p -g
$AERDIR/aergen.sh -n I26E13 -s 2100 -e 2120 -m 3 -a -x -i 2.6E-13 -z 147 -p -g
I would like to match the three digit number after -z and replace it with that number +1, so
$AERDIR/aergen.sh -n control -s 2100 -e 2120 -m 3 -a -x -z 145 -p -g
$AERDIR/aergen.sh -n Cl26E10 -s 2100 -e 2120 -m 3 -a -x -c 2.6E-10 -z 146 -p -g
$AERDIR/aergen.sh -n Br26E12 -s 2100 -e 2120 -m 3 -a -x -b 2.6E-12 -z 147 -p -g
$AERDIR/aergen.sh -n I26E13 -s 2100 -e 2120 -m 3 -a -x -i 2.6E-13 -z 148 -p -g
I've been playing around with submatch parameters and such, but have only managed to increment the first appearance of numbers in each line. How would I formulate a command to do this, say from line 203,$ ?

This is a job for submatch:
%s/-z \zs\d\+/\=submatch(0)+1/
The pattern -z \zs\d\+ matches one or more digits \d\+ preceeded by -z. Then \=submatch(0)+1 adds one to the matched number.

Related

grep parts of string with match and not match?

I have a log file which contains string errorCode:null or errorCode:404 etc. I want to find all occurrences where errorCode is not null.
I use:
grep -i "errorcode" -A 10 -B 10 app.2020-.* | grep -v -i "errorCode:null"`,
grep -v -i 'errorcode:[0-9]^4' -A 10 -B 10 app.2020-.*
but this is not the right regex match. How could this be done?
If you have gnu-grep then use a negative lookahead in regex as this with -P option:
grep -Pi 'errorcode(?!:null)' -A 10 -B 10 app.2020-.*
If you don't have gnu grep then try this awk:
awk '/errorcode/ && !/errorcode:null/' app.2020-.*
it would require more bit of code in awk to match equivalent of -A 10 -B 10 options of grep.
I have no idea why you are using -A 10 -B 10, I've just used the following command and everything is working fine:
grep -i "ErrorCode" test.txt | grep -v -i "Errorcode:null"
This the file content:
Errorcode:null
Errorcode:405
Errorcode:504
Nonsens
This is the output of the command:
Errorcode:405
Errorcode:504

how to make the below output of the command pass not fail

how to make the below output of the regex command pass not fail
grep -E '^[[:space:]]*-a[[:space:]]+always,exit[[:space:]]+-F[[:space:]]+arch=b32[[:space:]]+-S[[:space:]]+creat[[:space:]]+-S[[:space:]]+open[[:space:]]+-S[[:space:]]+openat[[:space:]]+-S[[:space:]]+truncate[[:space:]]+-S[[:space:]]+ftruncate[[:space:]]+-F[[:space:]]+exit=-EACCES[[:space:]]+-F[[:space:]]+auid>=500[[:space:]]+-F[[:space:]]+auid!=4294967295[[:space:]]+-k[[:space:]]+access[[:space:]]*$' /etc/audit/rules.d/*.rules | /usr/bin/awk '{print} END {if (NR != 0) print "pass" ; else print "fail"}'
I tried the below and still fail
echo -e "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access\n-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access\n-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access\n-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access" > /etc/audit/rules.d/access.rules

Maintain $ (dollar sign) when performing find and replace

My script appends a block of text to the end of a file.
### Start My Block
$IPT -A INPUT -s 8.8.8.8 -j ACCEPT
$IPT -A INPUT -s 8.8.8.4 -j ACCEPT
### End My Block
If my text block doesn't exists, it successfully appends the file as shown above using the following:
HEAD="### Start My Block"
TAIL="### End My Block"
REPLACEMENT_CONTENT="
\$IPT -A INPUT -s 8.8.8.8 -j ACCEPT
\$IPT -A INPUT -s 8.8.8.4 -j ACCEPT"
echo -e "$HEAD" >> $FILE
echo -e "$REPLACEMENT_CONTENT" >> $FILE
echo -e "$TAIL" >> $FILE
If my text block exists, it attempts to replace the block's contents using the following:
HEAD="### Start My Block"
TAIL="### End My Block"
REPLACEMENT_CONTENT="
\$IPT -A INPUT -s 4.4.4.4 -j ACCEPT
\$IPT -A INPUT -s 4.4.2.2 -j ACCEPT"
perl -0777 -i -pe "s/($HEAD).*(\\n$TAIL)/\$1$REPLACEMENT_CONTENT\\$2/s" $FILE
The problem is I lose the "$IPT" and end up using the following:
### Start My Block
-A INPUT -s 4.4.4.4 -j ACCEPT
-A INPUT -s 4.4.2.2 -j ACCEPT
### End My Block
When I output the above via ">>", with the dollar sign escaped \$, the $IPT is included. When I revisit the file to replace existing content between the $HEAD and $TAIL and use the perl function with an updated block, the escaped dollar sign doesn't seem to hold. My guess is it's being interpreted and I'm not sure how to prevent that if escaping isn't enough.
Does anyone know how I can modify the command above to maintain the "$IPT"?
Yes, you are right your $IPT get interpreted in your regex inside perl.
So, using \$IPT this you are escaping $ for the shell. But you also need to escape $ for perl, so that it shouldn't interpret. For that you should do like this:
REPLACEMENT_CONTENT="
\\\$IPT -A INPUT -s 8.8.8.8 -j ACCEPT
\\\$IPT -A INPUT -s 8.8.8.4 -j ACCEPT"
This escapes \ once and then $ itself sending perl \$ and thus it did not get interpreted.
OR
Just wrap REPLACEMENT_CONTENT in single quotes.
REPLACEMENT_CONTENT='
\$IPT -A INPUT -s 8.8.8.8 -j ACCEPT
\$IPT -A INPUT -s 8.8.8.4 -j ACCEPT'
And after that perl part:
perl -0777 -i -pe "s/($HEAD).*($TAIL)/\$1$REPLACEMENT_CONTENT\n\$2/s" $FILE

Why does grep -P on binary files sometimes match wrong bytes?

I'm trying to use grep -P to find specific byte sequences in potentially large binary files. However, it sometimes matches where it shouldn't - for example, here's a golfed-down case where it appears to simply "match over" a wrong \xc2 byte:
➜ alias bin2hex='xargs echo -n | od -An -tx1'
➜ echo -e '\x3e\x1f\xc2\x9d\xa0' > test.bin
➜ cat test.bin | bin2hex
3e 1f c2 9d a0
➜ grep -P '\x1f\x9d' test.bin
Binary file test.bin matches
➜ grep -Pao '\x1f\x9d' test.bin | bin2hex
1f c2 9d
Why does this happen?
And can it be avoided?
This command:
grep -P '\x1f\x9d' <<< $(echo -e '\x3e\x1f\xc2\x9d\xa0') | xargs echo -n | od -An -tx1
prints nothing with grep versions:
GNU grep 2.5.1
GNU grep 2.6.3
GNU grep 2.21
Are you sure your grep is not aliased to anything wrong (type grep)?
UPDATE: converting comments into answer
I can reproduce your problem with a different LANG value:
LANG=en_US.UTF-8; grep -P '\x1f\x9d' <<< $(echo -e '\x3e\x1f\xc2\x9d\xa0')
Binary file (standard input) matches
The problem is not reproduced with:
LANG=en_US; grep -P '\x1f\x9d' <<< $(echo -e '\x3e\x1f\xc2\x9d\xa0')

Using SED to replace a pattern causes extra characters to appear

I have a file and want to replace a pattern with another string.
#PBS -N bench1-M1-plt2-size15
#PBS -o /home/results/bench1-M1-plt2-size15.out
./run -d ./results/ --config=bench1-M1-plt2-size15.conf \
--results=bench1-M1-plt2-size15.res config/myConfig.txt -F 2000000
I use this command
sed 's/M1-[^-]*-[^-]/M1-plt32-size10/g' filename
However the output file looks like this:
#PBS -N M1-plt32-size100
#PBS -o /home/mahmood/gem5/results/M1-plt32-size100.out
./run -d ./results/ --config=bench1-M1-plt32-size100.conf \
--results=bench1-M1-plt32-size100.res config/myConfig.txt -F 2000000
Please note an extra '0' character after "size10". As you can see, in the SED command, size is set to 10, however the output file is "size100"
What is the problem and how can I fix that?
Your regex is not correct. You have [^-] which will match only 1 non-hyphen character. I believe this is what you intended:
sed 's/M1-[^-]*-[^\.]*/M1-plt32-size10/' filename
OUTPUT:
#PBS -N bench1-M1-plt32-size10
#PBS -o /home/results/bench1-M1-plt32-size10.out
./run -d ./results/ --config=bench1-M1-plt32-size10.conf \
--results=bench1-M1-plt32-size10.res config/myConfig.txt -F 2000000