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'. –
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.
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
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.
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.
Vous pouvez utiliser Vim en mode Ex:
ex -s -c '%s/a/b/g|x' file
%
sélectionner toutes les lignes
s
substitut
g
remplacement global
x
enregistrer et fermer
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).
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
!