Remove match and previous line

I need to remove the line containing "not dynamic executable" and the previous line from the stream using grep, awk, sed or whatever. My current working solution would be to flatten the whole stream to disable newlines, then replace the newline before my match with something else using sed, then use tr to add newlines, and then use grep -v ... I'm a little tired of artifacts with this approach, but I don't understand how else I can do this at the moment:

tr '\n' '|' | sed 's/|\tnot a dynamic executable/__MY_REMOVE/g' | tr '|' '\n'

      

EDIT:

Input is a list of mixed files piped to xargs ldd, basically I want to ignore all non-library file output as it has nothing to do with what I am doing next. I didn't want to use the lib * .so mask as it could be different.

+2


source to share


3 answers


Most simple with pcregrep

in multi-line mode:

pcregrep -vM '\n\tnot a dynamic executable' filename

      

If pcregrep

not available to you, then awk

or sed

also can be done by reading one line forward and skipping printing previous lines when the marker line appears.

You can be boring (and sane) with awk:

awk '/^\tnot a dynamic executable/ { flag = 1; next } !flag && NR > 1 { print lastline; } { flag = 0; lastline = $0 } END { if(!flag) print }' filename

      

I.e:

/^\tnot a dynamic executable/ {  # in lines that start with the marker
  flag = 1                       # set a flag
  next                           # and do nothing (do not print the last line)
}
!flag && NR > 1 {                # if the last line was not flagged and
                                 # is not the first line
  print lastline                 # print it
}
{                                # and if you got this far,
  flag = 0                       # unset the flag
  lastline = $0                  # and remember the line to be possibly
                                 # printed.
}
END {                            # in the end
  if(!flag) print                # print the last line if it was not flagged
}

      

But sed is fun:



sed ':a; $! { N; /\n\tnot a dynamic executable/ d; P; s/.*\n//; ba }' filename

      

Explanation:

:a                                  # jump label

$! {                                # unless we reached the end of the input:

  N                                 # fetch the next line, append it

  /\n\tnot a dynamic executable/ d  # if the result contains a newline followed
                                    # by "\tnot a dynamic executable", discard
                                    # the pattern space and start at the top
                                    # with the next line. This effectively
                                    # removes the matching line and the one
                                    # before it from the output.

                                    # Otherwise:
  P                                 # print the pattern space up to the newline
  s/.*\n//                          # remove the stuff we just printed from
                                    # the pattern space, so that only the
                                    # second line is in it

  ba                                # and go to a
}
                                    # and at the end, drop off here to print
                                    # the last line (unless it was discarded).

      

Or, if the file is small enough to store it entirely in memory:

sed ':a $!{N;ba}; s/[^\n]*\n\tnot a dynamic executable[^\n]*\n//g' filename

      

Where

:a $!{ N; ba }                                  # read the whole file into
                                                # the pattern space
s/[^\n]*\n\tnot a dynamic executable[^\n]*\n//g # and cut out the offending bit.

      

+5


source


Always remember that while grep and sed are line oriented, awk is write oriented and can therefore easily handle problems that span multiple lines.

You weren't supposed to post any sample input and expected output, but this seems like everything you need (using GNU awk for multi-char RS):



awk -v RS='^$' -v ORS= '{gsub(/[^\n]+\n\tnot a dynamic executable/,"")}1' file

      

+1


source


This might work for you (GNU sed):

sed 'N;/\n.*not a dynamic executable/d;P;D' file

      

This keeps the moving window from two lines and removes them if the search line is in the second. If not the first line is printed, then it is removed and then the next line is added and the process repeats.

+1


source







All Articles