grep точное совпадение двух частей строки

grep точное совпадение двух частей строки

Как использовать команду grep, чтобы получить часть строки, как показано ниже?

Нить:

orange:"orange", red:"apple", purple:"grape", yellow:"banana", green:"watermelon"
red:"strawberries", yellow:"lemon"

Что я хочу:

red:"apple" yellow:"banana"
red:"strawberries" yellow:"lemon"

Я попробовал это:

grep -oP '(red:\"[^\"]*).*(yellow:\"[^\"]*)'

решение1

В .*середине соответствует всему, т.е. purple:"grape"части. Вместо этого (предполагая, что вы хотите придерживаться GNU grep), я бы сопоставил каждую часть отдельно с помощью (foo|bar)конструкции "ИЛИ".

grep -oP '(red|yellow):\"[^\"]*"'

NB Мне пришлось добавить закрывающую ". Кроме того, вам не нужно экранировать ", поэтому вы можете использовать

grep -oP '(red|yellow):"[^"]*"'

В любом случае, это дает вам

red:"apple"
yellow:"banana"

затем соединить строки с пробелом между ними,

grep -oP '(red|yellow):"[^"]*"' | paste -sd ' ' -

Честно говоря, я бы, естественно, использовал sed.

sed -n 's/.*\(red:"[^"]*"\).*\(yellow:"[^"]*"\).*/\1 \2/p'

решение2

grepобычно не извлекает содержимое из строк. Он pвыводит строки, соответствующие rрегулярному eвыражению ( gглобально он назван в честь g/re/p edкоманды).

Однако некоторые реализации, такие как GNU grep, которую вы, судя по всему, используете, имеют возможность -oделать что-то из этого в виде расширения.

pcregrepидет еще дальше. Он -oможет принимать необязательный числовой аргумент для вывода содержимого группы захвата, а не всей совпавшей части строки.

pcregrep -o1 -o2 --om-separator=' ' '(red:"[^"]*").*(yellow:"[^"]*")'

Его возможности по-прежнему ограничены.

Чтобы извлечь информацию из строки и выполнить дополнительные преобразования, вам понадобится текстовый sпроцессор , как уже было показано здесь.ed

решение3

Вы действительно можете сделать это с grepпомощьюпредложено Спархоком, или с почти идентичным:

$  echo 'red:"apple", purple:"grape", yellow:"banana"' |      
        grep -oP '(red|yellow):".+?"' | perl -00pe 's/\n/ /'
red:"apple" yellow:"banana"

Лично я бы, наверное, сделал это с помощью perl:

$ echo 'red:"apple", purple:"grape", yellow:"banana"' | 
    perl -F, -ane 'map{print if /red|yellow/}@F'
red:"apple" yellow:"banana"

Связанный контент