Comment sed uniquement les lignes qui contiennent une chaîne donnée?


13

CONTRIBUTION:

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

PRODUCTION:

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

Donc en bref j'ai besoin de "sed" "sdfg" à "XXXX".

MAIS: uniquement dans les lignes contenant la chaîne "Select ASDF" .. Comment faire? (sed, awk, etc.: \)

Réponses:


19

Vous pouvez préfixer la plupart des commandes sed avec une adresse pour limiter les lignes auxquelles elles s'appliquent. Une adresse peut être un numéro de ligne ou une expression régulière délimitée par /.

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

Comme mentionné Peter.O, la commande telle qu'écrite ci-dessus remplacera la première occurrence de any sdfgdans la chaîne contenant Select ASDF. Si vous devez remplacer la correspondance exacte sdfguniquement dans le cas où elle se trouve dans la quatrième colonne, vous devez procéder comme suit:

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

1
Qu'en est-il d'un autre champ contenant sdfg ? par exemple. 5sdfga
Peter.O

Hmm, en fait ce n'est pas le problème aussi. J'ai mis à jour ma réponse.
rush

y a-t-il des options pour utiliser: sed '/ Sélectionnez ASDF / gs = sdfg = XXXX =' - donc je dois remplacer toutes les occurrences dans une ligne, pas seulement la première. mais sed donne une erreur si j'utilise "g"
LanceBaynes

1
Vous devez taper gaprès dernier =(à la fin de la scommande). Ce sera comme ça:sed '/Select ASDF/ s=sdfg=XXXX=g'
rush

7

Si vous ne modifiez la colonne 4 que si elle a la valeur exacte, il est logique d'utiliser des opérateurs d'égalité au lieu d'expressions régulières.

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

1
Vite! .. en le comparant, pour 1 million de lignes, avec awk de Birei et sed positionnel de Rush : 0m1.580s vs 0m3.792s vs 0m6.740s
Peter.O

1

En utilisant GNU awk:

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

Production:

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

MISE À JOUR : éviter IGNORECASEpour un non-GNU awk, et faire correspondre la casse. Merci à jw013 , qui a souligné ce détail:

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

1
Vous devez mentionner IGNORECASEest une extension GNU awk/ gawk.
jw013

1
@ jw013: Merci. Réponse mise à jour avec votre suggestion.
Birei

4
IGNORECASE est erroné dans ce cas, que ce soit GNU ou G'not .. Le critère dans la question est explicitement pour les majusculesASDF
Peter.O
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.