2015-02-17 3 views
2

Мне нужно удалить строку, содержащую «не динамический исполняемый файл» и предыдущую строку из потока, используя grep, awk, sed или что-то другое. Мое текущее рабочее решение состояло бы в том, чтобы выровнять весь поток, чтобы отключить новые строки, а затем заменить новую строку, предшествующую моему совпадению, чем-то другим, используя sed, затем использовать tr для добавления новых строк и затем использовать grep -v. Я несколько устал от артефактов с этим подходом, но я не вижу, как еще я могу к нему в данный момент:Удалить совпадение и предыдущую строку

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

EDIT:

Входной список смешанных файлов конвейеру xargs ldd, в основном я хочу игнорировать весь вывод о файлах без библиотеки, поскольку это не имеет никакого отношения к тому, что я делаю дальше. Я не хочу использовать Lib * .so маска, так что может concievably быть разными

ответ

5

Наиболее просто с pcregrep в режиме многострочного:

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

Если pcregrep не доступны, то awk или sed также может сделать это, прочитав одну строку вперед и пропустив печать предыдущих строк при появлении линии маркера.

Вы могли бы быть скучным (и разумным) с AWK:

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

То есть:

/^\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 
} 

Но СЭД весело:

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

Объяснение:

: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). 

Или, если файл достаточно мал, чтобы быть полностью сохранены в памяти:

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

Где

: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. 
1

Всегда имейте в виду, что в то время как Grep и СЭД являются линии ориентированных на AWK является Запись- и поэтому может легко справляться с проблемами, которые охватывают несколько строк.

Это предположение дал вам не размещать какие-либо входные выборки и ожидаемые результаты, но это звучит, как все, что вам нужно, это (с помощью GNU AWK для мульти-гольцов RS):

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

Это должен быть принятый ответ. – sjas

1

Это может работать для вас (ГНУ СЭД):

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

Это удерживает движущееся окно 2 строки и удаляет их обоих, если нужная строка найдена во втором. Если не первая строка печатается, а затем удаляется, а затем добавляется следующая строка и процесс повторяется.