PurnaChand Medisetty
PurnaChand Medisetty

Reputation: 83

replacing multi-line string with sed

what I have in the logs.

    ---POLICIES WITH 172.25.22.16 AS SOURCE ADDRESS---
    ---POLICIES WITH 172.25.22.16 AS DESTINATION ADDRESS---
    ---POLICIES WITH 172.25.22.17 AS SOURCE ADDRESS---
    some output
    ---POLICIES WITH 172.25.22.17 AS DESTINATION ADDRESS---
    ---POLICIES WITH 172.25.22.18 AS SOURCE ADDRESS---
    some output
    ---POLICIES WITH 172.25.22.18 AS DESTINATION ADDRESS---
    ---POLICIES WITH 172.25.22.19 AS SOURCE ADDRESS---

what is desired

    ---POLICIES WITH 172.25.22.16 AS SOURCE ADDRESS---
    None
    ---POLICIES WITH 172.25.22.16 AS DESTINATION ADDRESS---
    None
    ---POLICIES WITH 172.25.22.17 AS SOURCE ADDRESS---
    some output
    ---POLICIES WITH 172.25.22.17 AS DESTINATION ADDRESS---
    None
    ---POLICIES WITH 172.25.22.18 AS SOURCE ADDRESS---
    some output
    ---POLICIES WITH 172.25.22.18 AS DESTINATION ADDRESS---
    None
    ---POLICIES WITH 172.25.22.19 AS SOURCE ADDRESS---
    None

I tried sed 's:---\n---:----\nNone\n---/:g' which didn't do it. I need to do some replace on all the lines that ends with --- only when the next line begins with ---

Upvotes: 1

Views: 71

Answers (4)

potong
potong

Reputation: 58420

This might work for you (GNU sed):

sed -e ':a;/^---.*---$/{${aNone' -e 'b};n;//!b;iNone' -e 'ba}' file

If the current line begins and ends with --- and it is the last line of the file, append the string None. Otherwise, print the current line and fetch the next and if that also begins and ends with ---, insert None and repeat.

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 203502

You CAN do it with GNU sed (for -E, -z and recognizing \n as a newline char) with:

$ sed -Ez 's/(---\n)(---|$)/\1None\n\2/g' file
---POLICIES WITH 172.25.22.16 AS SOURCE ADDRESS---
None
---POLICIES WITH 172.25.22.16 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.17 AS SOURCE ADDRESS---
some output
---POLICIES WITH 172.25.22.17 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.18 AS SOURCE ADDRESS---
some output
---POLICIES WITH 172.25.22.18 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.19 AS SOURCE ADDRESS---
None

or GNU awk for multi-char RS and gensub():

$ awk -v RS='^$' -v ORS= '{$0=gensub(/(---\n)(---|$)/,"\\1None\n\\2","g")}1' file
---POLICIES WITH 172.25.22.16 AS SOURCE ADDRESS---
None
---POLICIES WITH 172.25.22.16 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.17 AS SOURCE ADDRESS---
some output
---POLICIES WITH 172.25.22.17 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.18 AS SOURCE ADDRESS---
some output
---POLICIES WITH 172.25.22.18 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.19 AS SOURCE ADDRESS---
None

but I'd highly recommend you use the following POSIX awk instead for portability, not reading the whole file into memory at once, and the ability to trivially enhance it if you need to make any changes:

$ cat tst.awk
/^---/ { if (NR>1) prt(); hdr=$0; next }
{ txt = txt ORS $0 }
END { prt() }
function prt() {
    print hdr (txt=="" ? ORS "None" : txt)
    hdr = txt = ""
}

$ awk -f tst.awk file
---POLICIES WITH 172.25.22.16 AS SOURCE ADDRESS---
None
---POLICIES WITH 172.25.22.16 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.17 AS SOURCE ADDRESS---
some output
---POLICIES WITH 172.25.22.17 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.18 AS SOURCE ADDRESS---
some output
---POLICIES WITH 172.25.22.18 AS DESTINATION ADDRESS---
None
---POLICIES WITH 172.25.22.19 AS SOURCE ADDRESS---
None

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 246807

I'd write

awk '
  /^---/ && prev ~ /^---/ {print "None"}
  {print; prev = $0}
  END {if (/^---/) print "None"}
' file

A little DRYer

awk '
  function none() {if ($0 ~ /^---/ && prev ~ /^---/) {print "None"}}
  {none(); print; prev = $0}
  END {none()}
' file

Upvotes: 2

Corentin Limier
Corentin Limier

Reputation: 5006

Using awk

awk '{
        if($0 ~ /^-{3}/){
            if(header==1){
                print "None"
            }; 
            header = 1
        }else{
            header = 0
        }
     }1
     END{
        if(header){
            print "None"
        }
     }' <input>

Shorter :

awk '!/^-{3}/{header=0;print;next}header{print "None"}{header=1}1;END{if(header){print "None"}}' <input>

Upvotes: 1

Related Questions