我有以下代码:
function replaceappend() {
awk -v old="^$2" -v new="$3" '
sub(old,new) { replaced=1 }
{ print }
END { if (!replaced) print new }
' "$1" > /tmp/tmp$$ &&
mv /tmp/tmp$$ "$1"
}
replaceappend "/etc/ssh/sshd_config" "Port" "Port 222"
它完美无缺,但我希望修改它,以便它取代整行内容而不仅仅是匹配的文本。
目前它会这样做:
Port 1234 -> Port 222 1234
我希望它能像这样工作:
Port 1234 -> Port 222
我找到的最接近的代码是here:
awk 'NR==4 {$0="different"} { print }' input_file.txt
这将用新内容替换匹配的整行。如何将其实现到我现有的代码中?
答案 0 :(得分:2)
如果要更换整条线,可以简化功能。为了避免传递给awk的变量中的元字符问题,我建议使用简单的字符串搜索:
awk -vold="$2" -vnew="$3" 'index($0,old)==1{f=1;$0=new}1;END{if(!f)print new}' "$1"
index
返回您要搜索的字符串的字符位置,从1开始。如果字符串old
位于该行的开头,则该行将更改为new
。块之后的1
始终为true,因此每行都打印出来(这是无条件{print}
块的常用简写。)
正如mklement0在注释中指出的那样,传递给awk的变量仍然需要进行一些解释:例如,字符串\n
将被解释为换行符{{1然而,这个问题远不如使用正则表达式那么重要,正如\t
之类的东西会匹配任何字符。
答案 1 :(得分:2)
只需改变:
sub(old,new) { replaced=1 }
为:
$0~old { $0=new; replaced=1 }
或:
sub(".*"old".*",new) { replaced=1 }
答案 2 :(得分:1)
同样,使用正则表达式来替换它:
replaceappend port.txt "Port.*" "Port 222"
在这里你要替换Port(如果它根据你的函数定义开始行)以及随后的任何内容,直到行结束时使用" Port 222"。
编辑:要将此部分功能转换为通话,请将其修改为
function replaceappend() {
awk -v old="^$2.*" -v new="$3" '
sub(old,new) { replaced=1 }
{ print }
END { if (!replaced) print new }
' "$1" > /tmp/tmp$$ &&
mv /tmp/tmp$$ "$1"
}