我正在尝试替换以下项目中的双反斜杠 (//):
//listen-on port 53 { 127.0.0.1; };
//listen-on-v6 port 53 { ::1; };
//recursion yes;
(我不知道是否有必要提及,但这些结果前面有几个空格。可能没有必要,但无论如何我还是想提一下。)
我对 sed 的了解有限(而且我不想使用其他任何东西),但出于某种原因,我无法将其删除。我也尝试使用“|”作为分隔符(或它的名称),但没有成功。
我尝试过的事情:
sed -i 's|^//recursion yes;*|recursion yes;*|' /etc/named.conf
和:
sed 's#^//[ \t]recursion$#recursion#g' /etc/named.conf
和
sed 's#^//[\t]recursion$#recursion#g' /etc/named.conf
(最后两个例子基于我在本网站某个不同主题中发现的内容,但也没有给出正确的结果。换句话说,它拒绝删除两个斜线(//)。
到目前为止,我只尝试使用“//recursion yes;”,因为我想先让它工作,但是我已经失败了。
请解释一下我做错了什么。谢谢!如果您愿意,有人也可以给出一个 awk 示例吗?这样我就可以将其用作 sed 的替代品。显然 awk 比 sed 更受欢迎?或者这只是个人偏好?
答案1
我不知道是否有必要提及,但这些结果前面有几个空格。可能没有必要,但无论如何我还是想提一下。
这非常重要 -如果用来^
将匹配模式锚定到字符串的开头。特别是:
^//recursion
只会在开头完全匹配^//[ \t]recursion
//
仅当正好位于开头且后面只有一个空格或制表符时才会匹配^//[\t]recursion
//
仅当正好位于开头且后面紧跟一个制表符时才会匹配
此外,你似乎对*
正则表达式的含义感到困惑(与 shell glob 或通配符不同) - 在正则表达式中,它是一个量词表示零个或多个前面的表达式。
假设空格在之前//
,我可能会这样做
sed -E '\:[ \t]*//recursion|listen-on: s://::' named.conf
分解
\:^[ \t]*//recursion|listen-on:
匹配零个或多个空格或制表符,后跟//
thenrecursion
或listen-on
s://::
//
仅在匹配的行上不进行任何替换
我使用:
它代替默认值的分隔符/
以避免与模式字符串混淆,并删除了-i
用于测试的。-E
启用扩展匹配,这使得|
平均值or
。
如果需要在 的两边允许任意空格//
,则可以将匹配表达式更改为
\:^[ \t]*//[ \t]*(recursion|listen-on):
如果愿意,您也可以使用[[:blank:]]
代替(甚至还包括垂直空格 - 在这种情况下,区别是没有意义的,因为您一次只处理一行)。[ \t]
[[:space:]]
使用 awk 时,情况会略有不同 - 至少如果您使用默认字段分隔符。在这种情况下,awk 会删除前导空格,因此您可以将 锚定//
到第一个字段的开头:
awk '$1 ~ /\/\/recursion/ {sub(/\/\//,"",$1)} 1'
请注意,只有 GNU awk 提供就地编辑选项。在 awk 中,您还可以考虑使用固定字符串匹配,例如
'$1 == "//recursion" || $1 == "//listen-on"
还要注意,这些方法都会从输出中去除前导空格。