搜索多个模式,其中包括单个文件中的双引号和两行上下的注释
Search for multiple patterns which included double quotes in single file and comment above and below two lines
我有一个非常大的文件,我需要在其中搜索 40 个形态。
如果模式在文件中匹配,则需要在 2 行之前和 2 行之后进行注释。
模式将如下所示:
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"
如果我需要搜索单个模式,那么我可以执行下面的 gvim 命令来完成任务。
:g/create_rev -name "2x_8_PLL"/-2,+2s/^/#
但是搜索模式更多的是40+。如何 search/grep 40 多个模式,以便我的预期输出如下所示:
#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
假设当你说“模式”时,你真正想要的是全行字符串匹配,然后在每个 Unix 机器上使用任何 shell 中的任何 awk,并通过可能需要的注释来处理重叠范围的情况而不是像其他解决方案那样对它们进行双重评论:
$ cat tst.awk
ARGIND==1 {
targets[[=10=]]
next
}
ARGIND==2 {
if ([=10=] in targets) {
for (i=FNR-2; i<=FNR+2; i++) {
if (i != FNR) {
hits[i]
}
}
}
next
}
FNR in hits {
[=10=] = "#" [=10=]
}
{ 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"
以上使用 GNU awk 作为 ARGIND。如果您没有 GNU awk,则将 ARGIND==1
更改为 FILENAME==ARGV[1]
,将 ARGIND==2
更改为 FILENAME==ARGV[2]
。
这可能对你有用(GNU grep 和 sed):
grep -A2 -B2 -nFf targets file |sed -En 's/^([0-9]+)-.*/s@^@#@/p' |sed -f - file
使用 grep 输出文件中与目标中的行相匹配的行。匹配项将按行编号并包含匹配项前后两行。
grep 命令的输出行通过管道传输到 sed 并用作 sed 脚本的地址,该脚本会在每个匹配地址的开头插入一个 #
。
从第一个 sed 调用的输出创建的 sed 脚本(通过 -f
命令行选项和 -
使用来自管道的标准输入)在第二个 sed 中使用编辑源文件的调用。
另一种仅使用 sed 的解决方案:
sed -E 's/.*/\#\n.*\n&\n.*\n#bb/' targets |
sed -Ee ':a;N;s/\n/&/4;Ta' -f - -e 'bc;:b;s/^([^#])/#/mg;s/^#//m3;:c;P;D' file
如果在 shell 的帮助下 ed
是 available/acceptable。
脚本myscript
#!/bin/sh
targets=
file=
{
ed -s "$targets" <<'EOF'
g|.|t.\
-1s|^|g/|\
s|$|/-2;+1s/^\(#\)\{0,1\}\(.*\)/#\2/\|\
+1s|.*|;+2;+1s/^\(#\)\{0,1\}\(.*\)/#\2/|
$a
,p
Q
.
,p
Q
EOF
} | ed -s "$file"
./myscript targets file
删除第一个,p
以将输出静音到stdout
如果需要 就地 编辑,请将第一个 Q
更改为 w
。
ed
可能会出现内存问题,具体取决于 big file
的大小。
我有一个非常大的文件,我需要在其中搜索 40 个形态。 如果模式在文件中匹配,则需要在 2 行之前和 2 行之后进行注释。 模式将如下所示:
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"
如果我需要搜索单个模式,那么我可以执行下面的 gvim 命令来完成任务。
:g/create_rev -name "2x_8_PLL"/-2,+2s/^/#
但是搜索模式更多的是40+。如何 search/grep 40 多个模式,以便我的预期输出如下所示:
#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
假设当你说“模式”时,你真正想要的是全行字符串匹配,然后在每个 Unix 机器上使用任何 shell 中的任何 awk,并通过可能需要的注释来处理重叠范围的情况而不是像其他解决方案那样对它们进行双重评论:
$ cat tst.awk
ARGIND==1 {
targets[[=10=]]
next
}
ARGIND==2 {
if ([=10=] in targets) {
for (i=FNR-2; i<=FNR+2; i++) {
if (i != FNR) {
hits[i]
}
}
}
next
}
FNR in hits {
[=10=] = "#" [=10=]
}
{ 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"
以上使用 GNU awk 作为 ARGIND。如果您没有 GNU awk,则将 ARGIND==1
更改为 FILENAME==ARGV[1]
,将 ARGIND==2
更改为 FILENAME==ARGV[2]
。
这可能对你有用(GNU grep 和 sed):
grep -A2 -B2 -nFf targets file |sed -En 's/^([0-9]+)-.*/s@^@#@/p' |sed -f - file
使用 grep 输出文件中与目标中的行相匹配的行。匹配项将按行编号并包含匹配项前后两行。
grep 命令的输出行通过管道传输到 sed 并用作 sed 脚本的地址,该脚本会在每个匹配地址的开头插入一个 #
。
从第一个 sed 调用的输出创建的 sed 脚本(通过 -f
命令行选项和 -
使用来自管道的标准输入)在第二个 sed 中使用编辑源文件的调用。
另一种仅使用 sed 的解决方案:
sed -E 's/.*/\#\n.*\n&\n.*\n#bb/' targets |
sed -Ee ':a;N;s/\n/&/4;Ta' -f - -e 'bc;:b;s/^([^#])/#/mg;s/^#//m3;:c;P;D' file
如果在 shell 的帮助下 ed
是 available/acceptable。
脚本myscript
#!/bin/sh
targets=
file=
{
ed -s "$targets" <<'EOF'
g|.|t.\
-1s|^|g/|\
s|$|/-2;+1s/^\(#\)\{0,1\}\(.*\)/#\2/\|\
+1s|.*|;+2;+1s/^\(#\)\{0,1\}\(.*\)/#\2/|
$a
,p
Q
.
,p
Q
EOF
} | ed -s "$file"
./myscript targets file
删除第一个
,p
以将输出静音到stdout
如果需要 就地 编辑,请将第一个
Q
更改为w
。ed
可能会出现内存问题,具体取决于big file
的大小。