Come sed solo quelle righe che contengono una determinata stringa?


13

INGRESSO:

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

PRODUZIONE:

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

Quindi in breve ho bisogno di "sed" "sdfg" a "XXXX".

MA: solo nelle righe che contengono la stringa "Seleziona ASDF". Come posso farlo? (sed, awk, ecc.: \)

Risposte:


19

È possibile aggiungere un prefisso alla maggior parte dei comandi sed con un indirizzo per limitare le linee a cui si applicano. Un indirizzo può essere un numero di riga o una regex delimitata da /.

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

Come menzionato Peter.O, il comando come scritto sopra sostituirà la prima occorrenza di qualsiasi sdfgnella stringa contenente Select ASDF. Se devi sostituire la corrispondenza esatta sdfgsolo nel caso in cui sia nella quarta colonna, dovresti procedere in questo modo:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'

1
Che dire di un altro campo contenente sdfg ? per esempio. 5sdfga
Peter.O

Hmm, in realtà non è questo il problema. Ho aggiornato la mia risposta.
corsa il

ci sono opzioni per usare: sed '/ Select ASDF / gs = sdfg = XXXX =' - quindi devo sostituire tutte le occorrenze in una riga, non solo la prima. ma sed dà errore se uso "g"
LanceBaynes

1
Devi digitare gdopo l'ultimo =(alla fine del scomando). Sarà così:sed '/Select ASDF/ s=sdfg=XXXX=g'
corsa

7

Se stai cambiando la colonna 4 solo se ha il valore esatto, allora ha senso usare gli operatori di uguaglianza invece delle espressioni regolari.

awk '$1 == "Select" && $2 == "ASDF" && $4 == "sdfg" {$4 = "XXXX"} {print}'

1
Veloce! .. confrontandolo, per 1 milione di righe, con il awk di Birei e la sed position di Rush : 0m1.580s contro 0m3.792s contro 0m6.740s
Peter.O

1

Utilizzando GNU awk:

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

Produzione:

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

AGGIORNAMENTO : evitare IGNORECASEper un non-GNU awke abbinare maiuscole e minuscole. Grazie a jw013 , che ha sottolineato questo dettaglio:

awk ' 
    /^Select ASDF/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile

1
Dovresti menzionare IGNORECASEè un'estensione awk/ GNU gawk.
jw013,

1
@ jw013: grazie. Risposta aggiornata con il tuo suggerimento.
Birei,

4
IGNORECASE è sbagliato in questo caso, che si tratti di GNU o G'not .. Il criterio in questione è esplicitamente per le maiuscoleASDF
Peter.O
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.