使用 awk 在文件中的字符串前添加一行

使用 awk 在文件中的字符串前添加一行

我想添加一行

allow = alaw

在字符串之前

nat = no

在文件sip.conf(或任何基于文本的文件)中。如果allow = alaw之前已经存在,nat = no则不应添加。并且该行不应添加在紧接该文件的[general]和后面的两个部分中[providertrunk0]

文件内容示例:

[general]
disallow = all
allow = ulaw
nat = no

[providertrunk0]
disallow = all
allow = ulaw
;allow = alaw
nat = no

secret =
nat = no
progressinband = yes

allow = ulaw
allow = alaw
nat = no
progressinband = yes

disallow = all
allow = ulaw
nat = no
progressinband = yes

更改后将是

[general]
disallow = all
allow = ulaw
nat = no

[providertrunk0]
disallow = all
allow = ulaw
;allow = alaw
nat = no

secret =
allow = alaw
nat = no
progressinband = yes

allow = ulaw
allow = alaw
nat = no
progressinband = yes

disallow = all
allow = ulaw
allow = alaw
nat = no
progressinband = yes

我的尝试

我试图排除[general][providertrunk0]部分的整个过程,但应用于整个文件,使用'/general/,/providertrunk0/{next}'如下:

awk -v add="allow = alaw" '/general/,/providertrunk0/{next} /^nat = no$/&&lastLine!=add{print add}{lastLine=$0}1' sip.conf '

但它没有给出正确的输出。

答案1

$ cat tst.awk
BEGIN {
    RS=""; ORS="\n\n"; FS=OFS="\n"
    skip["[general]"]
    skip["[providertrunk0]"]
    add = "allow = alaw"
    tgt = "nat = no"
}
!($1 in skip) {
    for (i=1; i<NF; i++) {
        if ( ($i != add) && ($(i+1) == tgt) ) {
            $i = $i OFS add
        }
    }
}
{ print }

$ awk -f tst.awk file
[general]
disallow = all
allow = ulaw
nat = no

[providertrunk0]
disallow = all
allow = ulaw
;allow = alaw
nat = no

secret =
allow = alaw
nat = no
progressinband = yes

allow = ulaw
allow = alaw
nat = no
progressinband = yes

disallow = all
allow = ulaw
allow = alaw
nat = no
progressinband = yes

将 RS 设置为 null 会使 awk 处于段落模式(请RS = ""参阅https://www.gnu.org/software/gawk/manual/gawk.html#Multiple-Line)因此您的输入被分成由空行分隔的多行记录。设置 ORS="\n\n" 可确保输出时记录之间有一个空行。将 FS 和 OFS 设置为“\n”表示记录被拆分为字段。因此,其余的代码就很简单了,因为您只需将特定字段(行)与问题中提到的值进行比较即可。skip[]只是我为存储第一个字段(第一行)字符串的任何数组编写的名称,我想忽略该字符串以便在该数组中进行进一步处理,然后对于每个记录测试,如果记录的第一个字段/行位于数组,如果是,则跳过对其进行处理。

相关内容