![如何使用 sed 替换文本文件中的非典型模式](https://linux22.com/image/1098286/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20sed%20%E6%9B%BF%E6%8D%A2%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E9%9D%9E%E5%85%B8%E5%9E%8B%E6%A8%A1%E5%BC%8F.png)
我有一个 MRTG 配置文件,其中包含以单词“Target”开头的行。现在在这些行中有一个以字符“#”开头并以字符“:”结尾的模式。
示例线可能看起来像这些(注意两种类型,但开始/结束标记仍然相同):
Target[192.168.0.1_Gi1_1]: #Gi1/1:[email protected]:::::2
Target[192.168.0.1_Gi1_31]: #Gi1/31:[email protected]:::::2
我需要让 sed 找到这些行并"#Gix/n:"
用 替换模式"ifInErrors#Gix/n&ifInErrors#Gix/n:"
,其中 x= 1-9
,n= 1-48
。
因此,上面显示的两条示例线将修改为:
Target[192.168.0.1_Gi1_1]: ifInErrors#Gi1/1&ifInErrors#Gi1/1:[email protected]:::::2
Target[192.168.0.1_Gi1_31]: ifInErrors#Gi1/31&ifInErrors#Gi1/31:[email protected]:::::2
答案1
您需要的是一个捕获组 - 您可以在括号中捕获所需的内容,并可以在替换中引用它。像这样:
grep ^[[:space:]]*Target file | sed 's/\(#Gi[1-9]\/[1-9][0-9]*\):/ifInErrors\1\&ifInErrors\1:/'
答案2
sed '/Target/s/\(#Gi[0-9]*_[0-9]*:\)/ifInErrors\1\&ifInErrors\1/' input.txt
sed '/Target/
相当于grep Target | sed
,只是少了一个进程和一个管道。
s/
表示“替换”,最常见的 sed 命令;s/foo/bar/
将替换字符串的实例富和酒吧, 例如。
/\(#Gi[0-9]*\/[0-9]*:\)
... 括号(需要用 转义\
)告诉 sed 将它们之间的所有内容标记为\1
(或第二个标记模式的 \2,第三个标记模式的 \3 等)。[0-9]*
表示“任意数量的数字”,并且\/
是转义的/
(需要转义,因为我将其用作/
sed 的分隔符;如果您使用另一个分隔符,例如|
,则无需转义 /)。因此,#Gi[0-9]*\/[0-9]*:
模式的意思是“以 # 开头,后跟 Gi,然后是任意数量的数字,然后是 /,然后是任意数量的数字,以 : 结尾”。
因此\1
匹配由模式检测到的任何字符串#Gi[0-9]*\/[0-9]*:
在问题中给出的第一个字符串中,
Target[192.168.0.1_Gi1_1]: #Gi1/1:[email protected]:::::2
## The pattern #Gi[0-9]*\/[0-9]*: will match the substring
#Gi1/1:
...因此/ifInErrors\1\&ifInErrors\1/
告诉 sed‘替换#Gi1/1:
为ifInErrors#Gi1/1:&ifInErrors#Gi1/1:
’。
一些额外的东西:如果你想只是打印以“目标”开头的行,进行 sed 替换,您可以使用以下行:
sed -n '/Target/s/\(#Gi[0-9]*\/[0-9]*:\)/ifInErrors\1\&ifInErrors\1/p'
-n
告诉 sed“不要打印输出”,p
最后的告诉它打印 sed 正在处理的行。
如果您想要覆盖原始文件,可以使用以下命令:
sed -i '/Target/s/\(#Gi[0-9]*\/[0-9]*:\)/ifInErrors\1\&ifInErrors\1/'