awkを使用してファイルの文字列の前に行を追加します。

awkを使用してファイルの文字列の前に行を追加します。

行を追加したい

allow = alaw

文字列の前に

nat = no

ファイルsip.conf(またはテキストベースのファイル)から。allow = alaw以前にすでに存在していた場合は、nat = no追加しないでください。そして、この行はファイルの[general]直後と2つのセクションに追加しないでください[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]AND部分のプロセス全体を除いて、以下を[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[]最初のフィールド(最初の行)文字列を格納する配列に対して作成した名前。その配列でさらに処理するためにその文字列を無視し、各レコードに対して最初のレコードがフィールド/行にあるかどうかをテストしたいと思います。配列の場合は処理をスキップします。

関連情報