web-dev-qa-db-fra.com

Comment trouver et remplacer une chaîne sans utiliser la commande Sed?

Comme nous le savons tous, sed est très efficace pour rechercher et remplacer une chaîne, par exemple trouver "a" et la remplacer par "b": sed 's/a/b/g'.

Est-il possible de le faire avec une autre commande ou un script Shell au lieu de sed?

Il s'agit d'un système Linux recadré pour TV qui n'a pas la commande sed. Je dois donc utiliser d'autres commandes ou scripts au lieu de sed 's/a/b/g'. –

16
binghenzq

Oui, il existe différentes façons de procéder. Vous pouvez également utiliser awk, Perl ou bash pour effectuer ces activités. En général, bien que sed soit probablement l'outil le plus approprié pour effectuer ces types de tâches.

Exemples

Disons que j'ai cet exemple de données, dans un fichier data.txt:

foo bar 12,300.50
foo bar 2,300.50
abc xyz 1,22,300.50

awk

$ awk '{gsub("foo", "foofoofoo", $0); print}' data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Perl

$ Perl -pe "s/foo/foofoofoo/g" data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Édition en ligne

Les exemples ci-dessus peuvent également modifier directement les fichiers. L'exemple Perl est trivial. Ajoutez simplement le -i commutateur.

$ Perl -pie "s/foo/foofoofoo/g" data.txt 

Pour awk c'est un peu moins direct mais tout aussi efficace:

$ { rm data.txt && awk '{gsub("foo", "foofoofoo", $0); print}' > data.txt; } < data.txt

Cette méthode crée un sous-shell avec les accolades '{...} `où le fichier est redirigé vers lui via ceci:

$ { ... } < data.txt

Une fois le fichier redirigé vers le sous-shell, il est supprimé puis awk est exécuté sur le contenu du fichier qui a été lu dans les sous-shells STDIN. Ce contenu est ensuite traité par awk et réécrit sous le même nom de fichier que nous venons de supprimer, le remplaçant efficacement.

12
slm

L'alternative classique pour les substitutions d'une seule lettre est la commande tr qui devrait être disponible sur à peu près n'importe quel système:

$ echo "foobar" | tr a b   
foobbr

tr est mieux que sed pour cela en fait puisque l'utilisation de sed (sans parler de Perl ou awk) pour les substitutions d'une seule lettre revient à utiliser un marteau pour tuer une mouche.

grep n'est pas conçu pour cela, il ne modifie pas son entrée, il ne fait que la rechercher.

Alternativement, vous pouvez utiliser les capacités de substitution de certains shells. Ici, en utilisant la syntaxe ksh, zsh ou bash:

$ foo="foobar"
$ echo "${foo//a/b}"
foobbr

Nous pourrions vous donner des réponses plus spécifiques si vous expliquiez exactement quel problème vous essayez de résoudre.

13
terdon

Vous pouvez utiliser Vim en mode Ex:

ex -s -c '%s/a/b/g|x' file
  1. % sélectionner toutes les lignes

  2. s substitut

  3. g remplacement global

  4. x enregistrer et fermer

4
Steven Penny

Si vous travaillez avec un fichier plutôt qu'avec un flux, vous pouvez utiliser l'éditeur de texte standard, ed:

printf '%s\n' ',s/a/b/g' w q | ed file.txt

Cela devrait être disponible sur n'importe quel * nix. La virgule dans ',s/a/b/g' indique à ed de travailler sur chaque ligne (vous pouvez également utiliser %, qui sera plus familier si vous avez l'habitude de vim), et le reste est une recherche et un remplacement standard. w lui dit d'écrire (enregistrer) le fichier, q lui dit de quitter.

Notez que, contrairement au sed de -i (et des options similaires dans d'autres outils), cela modifie le fichier sur place plutôt que de tricher avec des fichiers temporaires.

Je ne pense pas qu'il soit possible de faire fonctionner cela avec des flux, mais alors je ne sais pas grand-chose sur ed et je ne serais pas surpris s'il ait réellement cette capacité (la philosophie unix étant ce que c'est).

3
evilsoup

Utilisation de la commande ancêtre ed (dans laquelle -s signifie silencieux (silencieux) et la virgule avant les commandes signifie exécuter sur toutes les lignes):

Impression sur [~ # ~] stdout [~ # ~] :

ed -s file <<!
,s/a/b/g
,p
q
!

remplacement sur place:

ed -s file <<!
,s/a/b/g
w
q
!
2
Gilles Quenot