Как собирать только те строки, которые содержат данную строку?

13

ВХОД:

Select ASDF 325 sdfg sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg sdfg 4456 sdrg

ВЫХОД:

Select ASDF 325 XXXX sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg XXXX 4456 sdrg

Короче говоря, мне нужно "sed" "sdfg" в "XXXX".

НО: только в строках, которые содержат строку «Выбрать ASDF». Как я могу это сделать? (sed, awk и т. д. \)

LanceBaynes
источник

Ответы:

19

Вы можете добавить к большинству команд sed префикс с адресом, чтобы ограничить строки, к которым они применяются. Адрес может быть номером строки или регулярным выражением, разделенным символом /.

cat INPUT | sed '/Select ASDF/ s=sdfg=XXXX='

Как упоминалось в Peter.O, команда, как написано выше, заменит первое вхождение любого sdfgв строке, содержащей Select ASDF. Если вам нужно заменить точное соответствие sdfgтолько в том случае, если оно находится в четвертом столбце, вы должны пойти следующим образом:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'
порыв
источник
1
А как насчет другого поля, содержащего sdfg ? например. 5sdfga
Peter.O
Хм, на самом деле это тоже не проблема. Я обновил свой ответ.
Раш
есть ли варианты для использования: sed '/ Select ASDF / gs = sdfg = XXXX =' - поэтому мне нужно заменить все вхождения в строке, а не только первый. но sed выдает ошибку, если я использую «g»
LanceBaynes
1
Вам нужно ввести gпосле последней =(в конце sкоманды). Будет так:sed '/Select ASDF/ s=sdfg=XXXX=g'
Раш
7

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

awk '$1 == "Select" && $2 == "ASDF" && $4 == "sdfg" {$4 = "XXXX"} {print}'
Гленн Джекман
источник
1
Быстро! .. сравнивая это, для 1 миллиона строк, с awk Бирея и позиционным седом Раша : 0m1.580s против 0m3.792s против 0m6.740s
Peter.O
1

Использование GNU awk:

awk '
    BEGIN { IGNORECASE = 1 } 
    /^select asdf/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile

Выход:

Select ASDF 325 XXXX sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg XXXX 4456 sdrg

ОБНОВЛЕНИЕ : Избегайте IGNORECASEдля не-GNU awkи совпадать с учетом регистра. Спасибо jw013 , который указал на эту деталь:

awk ' 
    /^Select ASDF/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile
Birei
источник
1
Вы должны упомянуть IGNORECASE, это GNU awk/ gawkрасширение.
jw013
1
@ jw013: Спасибо. Обновленный ответ с вашим предложением.
Бирей
4
IGNORECASE не прав в этом случае, будь то GNU или G'not .. Критерий в вопросе явно для верхнего регистраASDF
Peter.O