Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.1k views
in Technique[技术] by (71.8m points)

bash - remove block of text between two lines based on content

I need to remove/filter a very large log file i managed to bring the log-file into blocks of text starting with a line containing <-- or --> ending with a line containing Content-Length: now if this block of text contains the word REGISTER it need to be deleted.

i found the flowing example:

 # sed script to delete a block if /regex/ matches inside it
 :t
 /start/,/end/ {    # For each line between these block markers..
    /end/!{         #   If we are not at the /end/ marker
       $!{          #     nor the last line of the file,
          N;        #     add the Next line to the pattern space
          bt
       }            #   and branch (loop back) to the :t label.
    }               # This line matches the /end/ marker.
    /regex/d;       # If /regex/ matches, delete the block.
 }                  # Otherwise, the block will be printed.
 #---end of script---

written by Russell Davies on this page

but i do not know how to transport this to a single line statement to use in a pipe my goal is to pipe a tail -F of the log file to the final version so it get updates by the minute

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Try this:

awk '/<--|-->/{rec=""; f=1} f{rec = rec $0 ORS} /Content-Length:/{ if (f && (rec !~ "REGISTER")) printf "%s",rec; f=0}' file

If it doesn't do what you want, provide more info on what you want along with sample input and output.

To break down the above, here's each statement on separate lines with some comments:

awk '
   /<--|-->/ {rec=""; f=1} # find the start of the record, reset the string to hold it and set a flag to indicate we've started processing a record
   f {rec = rec $0 ORS}    # append to the end of the string containing the current record
   /Content-Length:/{      # find the end of the record
      if (f && (rec !~ "REGISTER")) # print the record if it doesn't contain "REGISTER"
         printf "%s",rec
      f=0                  # clear the "found record" indicator
   }
' file

and if you have text between your records that you'd want printed, just add a test for the "found" flag not being set and invoke the default action of printing the current record (!f;)

awk '/<--|-->/{rec=""; f=1} f{rec = rec $0 ORS} !f; /Content-Length:/{ if (f && (rec !~ "REGISTER")) printf "%s",rec; f=0}' file

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...