web-dev-qa-db-fra.com

Inspectez la casse et remplacez par sed

J'essaie d'utiliser SED pour extraire du texte d'un fichier journal.

Je peux faire une recherche-remplacement sans trop de problèmes:

sed 's/foo/bar/' mylog.txt

Cependant, je souhaite rendre la recherche insensible à la casse. D'après ce que j'ai lu sur Google, il semble que l'ajout de i à la fin de la commande devrait fonctionner:

sed 's/foo/bar/i' mylog.txt

Cependant, cela me donne un message d'erreur:

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

Qu'est-ce qui ne va pas ici et comment puis-je résoudre le problème?

Je suis sur macOS, au cas où ça compte.

67
Craig Walker

Pour être clair: On macOS - à partir de Mojave (10.14) - sed - qui est le BSD implémentation - NE PREND PAS en charge la correspondance insensible à la casse - difficile à croire, mais vrai. Le réponse précédemment acceptée , qui affiche lui-même une commande GNUsed, a obtenu ce statut en raison de la Perl- solution à base mentionnée dans les commentaires.

Pour que cela la solution Perl fonctionne aussi avec caractères étrangers , via UTF -8, utilisez quelque chose comme:

Perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
  • -C active le support UTF-8 pour les flux et les fichiers, en supposant que les paramètres régionaux actuels sont basés sur UTF-8.
  • -Mutf8 indique à Perl d'interpréter le code source comme UTF-8 (dans ce cas, la chaîne passée à -pe) - c'est l'équivalent le plus court de le plus verbeux -e 'use utf8;'.Merci, Mark Reed

(Notez que en utilisant awk n'est pas une option non plus , comme awk sur macOS (c'est-à-dire, BWK awk , alias BSD awk ) semble ignorer complètement les paramètres régionaux - ses fonctions tolower() et toupper() ignorent les caractères étrangers (et sub()/gsub() not commencer par les drapeaux d’insensibilité à la casse).)

65
mklement0

Note de l'éditeur : Cette solution ne fonctionne pas sous macOS (prête à l'emploi), car elle s'applique uniquement àGNUsed, alors que macOS est livré avecBSDsed.

Capitaliser le 'je'.

sed 's/foo/bar/I' file
56
Wesley Rice

Une autre solution pour sed sur Mac OS X consiste à installer gsedde MacPorts ou HomeBrew, puis de créer l’alias sed='gsed'.

22
user4854746

Le sed FAQ adresse l'adresse search, insensible à la casse et étroitement liée. Il souligne que a) de nombreuses versions de sed supportent un drapeau et b) que c'est difficile à faire dans sed, vous devriez plutôt utiliser awk ou Perl.

Mais pour le faire dans POSIX sed, ils suggèrent trois options (adaptées pour être remplacées ici):

  1. Convertir en majuscule et stocker la ligne d'origine dans un espace réservé; cela ne fonctionnera pas pour les substitutions, cependant, car le contenu original sera restauré avant l'impression, il ne sert donc que pour l'insertion ou l'ajout de lignes en fonction d'une correspondance insensible à la casse.

  2. Peut-être que les possibilités sont limitées à FOO, Foo et foo. Ceux-ci peuvent être couverts par

    s/FOO/bar/;s/[Ff]oo/bar/
    
  3. Pour rechercher toutes les correspondances possibles, on peut utiliser des expressions entre crochets pour chaque caractère:

    s/[Ff][Oo][Oo]/bar/
    
2
Benjamin W.

La version Mac de sed semble un peu limitée. Une façon de contourner ce problème consiste à utiliser un conteneur Linux (via Docker) qui possède une version utilisable de sed:

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'
1
user1307434

J'ai eu un besoin similaire, et est venu avec ceci:

cette commande pour trouver simplement tous les fichiers:

grep -i -l -r foo ./* 

celui-ci pour exclure this_Shell.sh (si vous placez la commande dans un script appelé this_Shell.sh ), lancez la sortie sur la console pour voir ce qui s'est passé, puis utilisez sed sur chaque nom de fichier texte foo avec barre:

grep -i -l -r --exclude "this_Shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 

J'ai choisi cette méthode, car je n'aimais pas avoir tous les horodatages modifiés pour les fichiers non modifiés. alimenter le résultat de grep ne permet de regarder que les fichiers avec le texte cible (donc susceptible d'améliorer aussi les performances/la vitesse)

assurez-vous de sauvegarder vos fichiers et de tester avant d'utiliser. Peut ne pas fonctionner dans certains environnements pour les fichiers contenant des espaces incorporés. (?)

0
gojimmypi

Si vous effectuez une recherche de motif en premier, par exemple,

/pattern/s/xx/yy/g

alors vous voulez mettre la I après le motif:

/pattern/Is/xx/yy/g

Exemple:

echo Fred | sed '/fred/Is//willma/g'

renvoie willma; sans la I, il retourne la chaîne intacte (Fred).

0
CBB