用sed替换多行字符串

时间:2019-06-17 15:37:18

标签: bash awk sed

我在日志中有什么。

    ---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---

需要什么

    ---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

我尝试了sed's:--- \ n ---:---- \ nNone \ n --- /:g',但没有这样做。 仅在下一行以---

开头时,我才需要对所有以---结尾的行进行替换。

4 个答案:

答案 0 :(得分:2)

我会写

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

一些干燥器

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

答案 1 :(得分:2)

您可以使用GNU sed(对于-E-z并将\n识别为换行符)进行以下操作:

$ 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

或用于多字符RS和gensub()的GNU awk:

$ 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

但是我强烈建议您使用以下POSIX awk来提高可移植性,而不是一次将整个文件读入内存,并且如果需要进行任何更改,可以轻松增强它:

$ 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

答案 2 :(得分:1)

使用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>

答案 3 :(得分:1)

这可能对您有用(GNU sed):

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

如果当前行以---开始和结束,并且它是文件的最后一行,请附加字符串None。否则,打印当前行并获取下一行,如果该行也以---插入 None开始和结束并重复。