Как избежать появления новых строк с grep-o для нескольких совпадений в одной строке (на тексте из нескольких строк)

Как избежать появления новых строк с grep-o для нескольких совпадений в одной строке (на тексте из нескольких строк)

29.01.2020 11:28:51 Просмотров 23 Источник

У меня есть следующий текст::

aaa rr tt zz pp
aaa pp xx yy uu zz

И нужно извлечь все' aaa',' zz 'и' xx ' шаблон и распечатать их на одной строке, как это:

aaa zz
aaa xx zz

Лучшее, что я нашел, это grep -oP 'aaa|xx|zz', но это возвращает каждый шаблон, найденный на новой строке:

aaa
zz
aaa
xx
zz

Я попытался добавить что-то вроде tr -d '\n', но в этом случае он возвращает все матчи на одной строке, что не то, что я хочу.

NB: мне нужно решение, которое поддерживает регулярное выражение с ненасытным регулярным выражением, поскольку шаблоны поиска будут выглядеть следующим образом:^.+?,|,IN:.+?\-|,OUT:.+?-|State.+?[$,]

У вопроса есть решение - Посмотреть?

Ответы - Как избежать появления новых строк с grep-o для нескольких совпадений в одной строке (на тексте из нескольких строк) / How to avoid having newlines with grep -o for multiple match at the same line (on a text of several lines)

tripleee

29.01.2020 12:35:25

Предполагая , что у вас есть grep -P, вот простой постпроцессор Awk, чтобы перестроить выходные данные в нужный формат.

grep -Pno '^.+?,|,IN:.+?\-|,OUT:.+?-|State.+?[$,]' - /dev/null <file |
awk 'BEGIN { re="^\\(standard input\\):[1-9][0-9]*:" }
    $0 ~ re { sep="\n"; sub(re, "") }
    { if(NR>1) printf "%s", sep; printf "%s", $0; sep=" " }
    END { if(sep) printf "\n" }'

Если результаты grepмогут случайно вывести префикс, который выглядит как (standard input):1:из фактического соответствия, это не будет работать.

Это из BSD grep; если ваш локальный grepвыводит префикс имени файла другого формата для стандартного ввода (или если вам нужно выполнить рефакторинг для чтения ряда именованных файлов вместо стандартного ввода), регулярное выражение Awk необходимо будет соответствующим образом адаптировать.

https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964175#comment106049021_59964175
Спасибо Tripleee, я попробовал несколько машин, но не смог заставить его работать. Тем не менее, идея добавления-n на grep была очень хороша, поэтому я сделал свою собственную версию: awk-F': '' {curr = $1; sub("^[1-9][0-9]*:", ""); если(прэв & & прэв!=curr) {print STR; STR=$0;} else {if (!пред') стр=$0; стр=нибудь на ул. "" $0;} / г= - Ворка;} конец {печати стр}'
Является ответом!
Wiktor Stribiżew

29.01.2020 12:45:18

Вы можете использовать

 while IFS= read -r line; do
   echo $(grep -oP 'aaa|xx|zz' <<< "$line");
 done < file

То есть,

  1. Читать входной файл строка за строкой
  2. Получите ваши совпадения с командой grep не заключен в двойные кавычки.

Если у вас есть определенные пробелы внутри совпадений, которые вы хотите сохранить, рассмотрите возможность использования

$(...)

Таким образом, вы получите совпадения по строке через пробел. Вы можете использовать любой пользовательский разделитель в команде while IFS= read -r line; do echo "$(grep -oP 'aaa|xx|zz' <<< "$line" | awk '{ printf "%s", $0" "}')"; done < file (после awk).

https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106046396_59964349
Вам не нужен Awk, если вы используете (тогда не) бесполезное echo, или наоборот.
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106046472_59964349
@tripleee если бы вы могли предоставить вариант команды, которую вы имеете в виду, это было бы полезно. Я попытался обойтись без него, но это было единственное, что сработало.
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106046558_59964349
while IFS= read -r line; do echo $(grep -oP 'aaa|xx|zz' <<<"$line"); done <<$'aaa bb cc\nzz xx yy\nboo baa
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106047330_59964349
Ну не совсем; оболочка сглаживает пробелы, когда вы передаете строку без кавычек, например, в результате подстановки команды. Эквивалентно echo "$(grep -oP 'aaa|xx|zz' | awk '{ printf "%s", $0 }')"будет работать и правильно цитировать выходные данные из оболочки. Это лучший подход, если выходные grepмогут содержать нерегулярные пробелы и / или подстановочные знаки без кавычек. Смотрите также stackoverflow.com/questions/10067266/…
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106047433_59964349
@tripleee да, ввод образца OP слишком упрощен
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106048972_59964349
Спасибо, это работает очень хорошо, но это очень медленно (при использовании сложных регулярных выражений)
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106049166_59964349
@xtruder99 это может быть проблемой с регулярным выражением. Твой ^.+?,|,IN:.+?\-|,OUT:.+?-|State.+?[$,]очень неэффективно, и я боюсь ошибиться. Что вы хотите сопоставить с [$,]? Вы понимаете, что он соответствует $или ,вам нужно ,. Кроме того , нет необходимости использовать ^[^,]*,|,IN:[^-]*-|,OUT:[^-]*|State[^,]*,, использовать Pс этим шаблоном, так как больше нет специальных конструкций PCRE. Если вводимый текст длинный, ленивый точечный узор может быть действительно опасным узором.
https://stackoverflow.com/questions/59963112/how-to-avoid-having-newlines-with-grep-o-for-multiple-match-at-the-same-line-o/59964349#comment106054054_59964349
@WiktorStribiżew ну ваши аргументы о уместности моего регулярного выражения не принимаются, но в любом случае я сделал больше тестов, и действительно производительность ужасна на cygwin (например, обработка 3 строк/секунд), но не очень заметна на родном linux. Так что я приму это предложение. :)
Закрыть X