I have a very large file where I need to search for 40 patterns. If pattern got matched in the file then need to comment before 2 lines and after 2 lines. Patterns will be like as shown below:
1.create_rev -name "2x_8_PLL"
2.create_generated_rev -name "76_L"
3.create_rev -name "PCS_T0"
4.create_generated_rev -name "x544_P"
If I need to search for single pattern then I can execute below gvim command to accomplish the task.
:g/create_rev -name "2x_8_PLL"/-2,+2s/^/#
But the search patterns are more in number 40 plus. How to search/grep for 40+ patterns such that my expected output as shown below:
#pp
#oo
create_rev -name "2x_8_PLL"
#aa
#bb
hh
#ii
#jj
create_generated_rev -name "76_L"
#cc
#dd
create_rev -name "PCS_T0"
#ee
#ff
gg
This might work for you (GNU grep and sed):
grep -A2 -B2 -nFf targets file |sed -En 's/^([0-9]+)-.*/\1s@^@#@/p' |sed -f - file
Use grep to ouput lines in the file matching the lines in the targets. The matches will be line numbered and contain two lines before and after the matches.
The lines output from the grep command are piped into sed and used as addresses for a sed script, which inserts a # at the start of each matching address.
The sed script created from the ouput of the first sed invocation (by way of the -f command line option and the - which uses stdin from the pipe) is used in the second sed invocation which edits the source file.
Another solution using sed only:
sed -E 's/.*/\\#\\n.*\\n&\\n.*\\n#bb/' targets |
sed -Ee ':a;N;s/\n/&/4;Ta' -f - -e 'bc;:b;s/^([^#])/#\1/mg;s/^#//m3;:c;P;D' file
Assuming that when you say "pattern" what you really want is full-line string matching then using any awk in any shell on every Unix box and handling cases of overlapping ranges by commenting them as presumably required and not double-commenting them as could happen with other solutions:
$ cat tst.awk
ARGIND==1 {
targets[$0]
next
}
ARGIND==2 {
if ($0 in targets) {
for (i=FNR-2; i<=FNR+2; i++) {
if (i != FNR) {
hits[i]
}
}
}
next
}
FNR in hits {
$0 = "#" $0
}
{ print }
$ awk -f tst.awk targets file file
#pp
#oo
create_rev -name "2x_8_PLL"
#aa
#bb
hh
#ii
#jj
create_generated_rev -name "76_L"
#cc
#dd
create_rev -name "PCS_T0"
#ee
#ff
gg
$ cat targets
create_rev -name "2x_8_PLL"
create_generated_rev -name "76_L"
create_rev -name "PCS_T0"
create_generated_rev -name "x544_P"
The above uses GNU awk for ARGIND. If you don't have GNU awk then change ARGIND==1 to FILENAME==ARGV[1] and ARGIND==2 to FILENAME==ARGV[2].
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With