awk 在找到匹配项时替换整行

Awk replace entire line when match is found

我有以下代码:

function replaceappend() {
    awk -v old="^" -v new="" '
        sub(old,new) { replaced=1 }
        { print }
        END { if (!replaced) print new }
    ' "" > /tmp/tmp$$ &&
    mv /tmp/tmp$$ ""
}

replaceappend "/etc/ssh/sshd_config" "Port" "Port 222"

它工作得很好,但我希望对其进行修改,以便它替换整行内容,而不仅仅是匹配的文本。

目前它会这样做:

Port 1234 -> Port 222 1234

我希望它像这样工作:

Port 1234 -> Port 222

找到我能找到的最接近的代码 here:

awk 'NR==4 {[=13=]="different"} { print }' input_file.txt

这将用新内容替换整行匹配项。我怎样才能将它实现到我现有的代码中?

同样,对要替换的内容使用正则表达式:

replaceappend port.txt "Port.*" "Port 222"

在这里,您要用 "Port 222".

替换 Port(如果它开始该行,根据您的函数定义)加上直到该行结尾的任何内容

编辑:要使这部分功能成为函数的一部分而不是在调用中需要它,请将其修改为

function replaceappend() {
    awk -v old="^.*" -v new="" '                                                                                                        
        sub(old,new) { replaced=1 }                                                                                                         
        { print }                                                                                                                           
        END { if (!replaced) print new }                                                                                                    
    ' "" > /tmp/tmp$$ &&
    mv /tmp/tmp$$ ""
}

如果你想替换整行,你可以简化你的函数。为了避免传递给 awk 的变量中的元字符出现问题,我建议也使用简单的字符串搜索:

awk -vold="" -vnew="" 'index([=10=],old)==1{f=1;[=10=]=new}1;END{if(!f)print new}' ""

index returns要搜索的字符串的字符位置,从1开始。如果字符串old在行首,则该行更改为 new 的值。块后的 1 始终为真,因此打印每一行(这是无条件 {print} 块的常见 shorthand)。

正如 mklement0 在评论中指出的那样,您传递给 awk 的变量仍然需要进行一些解释:例如,字符串 \n 将被解释为换行符,\t 作为制表符等。但是,这个问题比使用正则表达式要小得多,在正则表达式中 . 之类的东西可以匹配任何字符。

只需更改:

sub(old,new) { replaced=1 }

至:

[=11=]~old { [=11=]=new; replaced=1 }

或:

sub(".*"old".*",new) { replaced=1 }