2

I want to add two line

allow = alaw
allow = g729

before a string

nat = no

in a file sip.conf (or any text based file). If allow = alaw and allow = g729 already exists before nat = no it should not be added. This script will run every hour. And the line should not be added in the two sections immediately after [general] and [providertrunk0] of the file.

Example file content:

[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
allow = g729
nat = no
progressinband = yes

expected output

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

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

secret =
allow = alaw
allow = g729
nat = no
progressinband = yes

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

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

My attempt

cat addCodec.awk

BEGIN {
    RS=""; ORS="\n\n"; FS=OFS="\n"
    skip["[general]"]
    skip["[providertrunk0]"]
    addCodec = "allow = alaw\nallow = g729"
    tgt = "nat = no"
}
!($1 in skip) {
    for (i=1; i<NF; i++) {
        if ( ($i != addCodec) && ($(i+1) == tgt) ) {
            $i = $i OFS addCodec
        }
    }
}
{ print }
awk -f addCodec.awk sip.conf

this script works if both line does not exist , it will add them. If a single line exist then I am stuck , what if condition I need to use.

8
  • i'm not specialist in awk but as I understand $i gives single line but you compare it with string which has two lines "allow = alaw\nallow = g729" - so it can't be correct. And maybe you should check separatelly $i == tgt && $(i-1) == "allow = g729" and later $i == tgt && $(i-2) == "allow = alaw" – furas Aug 4 '20 at 10:14
  • Is the line ;allow = alaw really supposed to be that in the [providertrunk0] block or is the leading ; a mistake? If it is a mistake then please fix your example. – Ed Morton Aug 4 '20 at 12:53
  • 1
    So you could have lines like that in your other blocks too? So then when looking for allow = alaw if ;allow = alaw is present we should ignore it? If ;allow = alaw is present in a block where we otherwise want to add it, should we remove or uncomment it or leave it or what? – Ed Morton Aug 4 '20 at 13:00
  • 1
    Also - what if allow = alaw and allow = g729 exist in the block but there's another line between them and nat = no? What if they exist but there's another line between them? What if they exist after nat = no but in the same block. Please edit your question to describe how all the different cases should be handled or state if they can't occur, and make sure your sample input/output covers all possible cases. – Ed Morton Aug 4 '20 at 13:07
  • 1
    There's nothing to discuss - just make sure your question covers all your use cases so we can help you come up with a script that covers them all rather than a script that only covers the one sunny day case you've described so far. – Ed Morton Aug 4 '20 at 13:30
1

I'm not specialist in awk (but python) but $i gives single line and you compare it with string which have two lines "allow = alaw\nallow = g729" - and this is problem. You should check every line separatelly.

I created code which check $(i-1) and $(i-2) and compare separatelly with "allow = alaw" (FIRST) and "allow = g729"(SECOND). This way I split it into three situations

FIRST - exist,  SECOND - missed
FIRST - missed, SECOND - missed
FIRST - missed, SECOND - exist

and add different value to $i or $(i-1)


BEGIN {
    RS=""; ORS="\n\n"; FS=OFS="\n"
    skip["[general]"]
    skip["[providertrunk0]"]
    addCodec1 = "allow = alaw"
    addCodec2 = "allow = g729"
    tgt = "nat = no"
}
!($1 in skip) {
    for (i=1; i<NF; i++) {
        if ($(i) == tgt) {
            # FIRST - exist, SECOND - missed
            if ( ($(i-1) == addCodec1) ) {
                $i = addCodec2 OFS $i
            }
            # FIRST - missed, SECOND - missed
            else if ( ($(i-1) != addCodec1) && ($(i-1) != addCodec2) ) {
                $i = addCodec1 OFS addCodec2 OFS $i 
            }
            # FIRST - missed, SECOND - exist
            else if ( ($(i-2) != addCodec1) && ($(i-1) == addCodec2)  ) {
                $(i-1) = addCodec1 OFS $(i-1)
            }
        }
    }
}
{ print }

BTW: To make it more unviveral (and simpler) I would run it two times with different arguments.

First to put only "allow = g729" before "nat = no", second to put only "allow = alaw" before "allow = g729".

This way I could run it again to put "third line" befor "allow = alaw" and run it again to put "fourth line" befor "third line", etc.

0

Modifying your existing attempt. The complexity of looking at the various possible scenarios is encapsulated inside a user defined function fx(). Depending on what index the tgt line is found, the various possible scenarios are charted.

$ cat addCodec.txt
BEGIN {
    RS=""; ORS="\n\n"; FS=OFS="\n"
    skip["[general]"]
    skip["[providertrunk0]"]
    e1 = "allow = alaw"
    e2 = "allow = g729"
    a[e2] = a[e1] = 1
    addCodec = e1 OFS e2
    tgt = "nat = no"
}
!($1 in skip) {
    for (i=1; i<=NF; i++) {
        if ($i "" == tgt) {
          fx(i)
          break
        }
    }
}
{ print }
function fx(i,   cond) {
  cond = (i>2 ? (a[$(i-2)]+0) : 0) "" (i>1 ? (a[$(i-1)]+0) : 0)
  if      ( cond "" == "11" ) { $(i-2) = e1; $(i-1) = e2 }
  else if ( cond "" == "01" ) { $(i-1) = addCodec        }
  else if ( cond    ~  /0$/ ) { $(i) = addCodec OFS $(i) }
}

$ awk -f addCodec.txt file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.