Jak uwodzić tylko te linie, które zawierają podany ciąg?

13

WEJŚCIE:

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

WYNIK:

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

Krótko mówiąc, muszę „sed” „sdfg” do „XXXX”.

ALE: tylko w wierszach zawierających ciąg „Wybierz ASDF”. Jak mogę to zrobić? (sed, awk itp.: \)

LanceBaynes
źródło

Odpowiedzi:

19

Możesz poprzedzić większość poleceń sed adresem, aby ograniczyć linie, do których się odnoszą. Adres może być numerem linii lub wyrażeniem regularnym ograniczonym przez /.

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

Jak wspomniano Peter.O, polecenie jak napisano powyżej zastąpi pierwsze wystąpienie dowolnego sdfgciągu zawierającego Select ASDF. Jeśli chcesz zastąpić dokładne dopasowanie sdfgtylko w przypadku, gdy jest to w czwartej kolumnie, powinieneś iść w ten sposób:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'
wysypka
źródło
1
Co z innym polem zawierającym sdfg ? na przykład. 5sdfga
Peter.O
Hmm, właściwie to też nie jest problem. Zaktualizowałem swoją odpowiedź.
pęd
czy są jakieś opcje użycia: sed '/ Select ASDF / gs = sdfg = XXXX =' - więc muszę zastąpić wszystkie wystąpienia w linii, nie tylko pierwszą. ale sed daje błąd, jeśli
użyję
1
Trzeba wpisać gpo ostatnim =(na końcu spolecenia). Będzie to tak:sed '/Select ASDF/ s=sdfg=XXXX=g'
spieszyć
7

Jeśli zmieniasz tylko kolumnę 4, jeśli ma ona dokładną wartość, zastosowanie operatorów równości zamiast wyrażeń regularnych ma sens.

awk '$1 == "Select" && $2 == "ASDF" && $4 == "sdfg" {$4 = "XXXX"} {print}'
Glenn Jackman
źródło
1
Szybki! .. porównując, dla 1 miliona linii, z awk Birei i sedem pozycjonującym Rusha : 0m1,580s vs. 0m3.792s vs. 0m6.740s
Peter.O
1

Używanie GNU awk:

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

Wynik:

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

AKTUALIZACJA : Unikaj IGNORECASEdla nie-GNU awki dopasuj wielkość liter. Dzięki jw013 , który wskazał ten szczegół:

awk ' 
    /^Select ASDF/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile
Birei
źródło
1
Powinieneś wspomnieć IGNORECASEo GNU awk/ gawkrozszerzeniu.
jw013
1
@ jw013: Dziękuję. Zaktualizowana odpowiedź z twoją sugestią.
Birei
4
IGNORECASE nie ma racji w tym przypadku, niezależnie od tego, czy jest to GNU, czy G'not. Kryterium w pytaniu jest wyraźnie dla wielkich literASDF
Peter.O