Як сідати лише ті рядки, які містять заданий рядок?


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 тощо) \)

Відповіді:


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 '/ Виберіть 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 мільйон рядків, з биком Біка та позиційним седом Rush : 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

1
Ви повинні згадати IGNORECASE- це GNU awk/ gawkрозширення.
jw013

1
@ jw013: Дякую Оновлена ​​відповідь з вашою пропозицією.
Бірей

4
IGNORECASE помиляється в цьому випадку, чи це GNU чи G'not .. Критерій у питанні явно для верхнього регіструASDF
Peter.O
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.