![我想搜索并替换模式](https://linux22.com/image/6383/%E6%88%91%E6%83%B3%E6%90%9C%E7%B4%A2%E5%B9%B6%E6%9B%BF%E6%8D%A2%E6%A8%A1%E5%BC%8F.png)
我想搜索文件中的每条记录(记录由空行定义)以查找模式NAME#AAAA
。如果匹配,则#
在记录前面插入一个,并在记录末尾age
插入一行。age NIL
输入文件:
NAME#AAAA
STD 1
SEC A
AGE 5
NAME#BBBB
STD 2
SEC B
AGE 6
NAME#CCCC
STD 3
SEC C
AGE 7
NAME#AAAA
STD 4
AGE 9
NAME#AAAA
STD 7
SEC A
AGE 12
预期产出
NAME#AAAA
STD 1
SEC A
#AGE 5
AGE NIL
NAME#BBBB
STD 2
SEC B
AGE 6
NAME#CCCC
STD 3
SEC C
AGE 7
NAME#AAAA
STD 4
#AGE 9
AGE NIL
NAME#AAAA
STD 7
SEC A
#AGE 12
AGE NIL
答案1
每当您看到由空行(“段落”,如果您愿意的话)分隔的记录时,Perl 的“段落模式”通常是一个很好的解决方案:
$ perl -00lpe 'if(/NAME#AAAA/){s/\bAGE\s/#$&/; s/$/\nAGE NIL/;}' file
NAME#AAAA
STD 1
SEC A
#AGE 5
AGE NIL
NAME#BBBB
STD 2
SEC B
AGE 6
NAME#CCCC
STD 3
SEC C
AGE 7
NAME#AAAA
STD 4
#AGE 9
AGE NIL
NAME#AAAA
STD 7
SEC A
#AGE 12
AGE NIL
解释
-00
:这会激活 Perl 的段落模式,其中每个“段落”(一组非空行直到空行)都被视为“行”。-l
:从每个输入记录(每个段落)中删除尾随换行符,并向每个print
调用添加一个换行符。-pe
:在应用给定的脚本后打印每个输入记录-e
。
因此,这些标志可以perl
读取输入文件,将脚本应用于每个记录,然后打印结果。脚本本身的作用是:
if(/NAME#AAAA/)
:如果此记录匹配NAME#AAAA
。s/\bAGE\s/#$&/
:s/foo/bar/
是替换运算符。它将替换foo
为bar
。在这里,我将替换AGE
为 本身,前面加#
。\b
匹配单词边界,并将排除ADAGE
匹配中的 之类的内容。$&
是一个特殊变量,表示“匹配的任何内容”。因此,s/\bAGE\s/#$&/
将替换AGE
为#AGE
。s/$/\nAGE NIL/
:$
匹配记录的结尾。因此,用其他内容替换它会附加到记录的末尾。此命令附加AGE NIL
到匹配记录的末尾。
请注意,此处的所有操作均区分大小写。如果您需要不区分大小写的匹配,请使用以下命令:
perl -00lpe 'if(/NAME#AAAA/i){s/\bAGE\s/#$&/i; s/$/\nAGE NIL/i;}' file