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


16

Comme nous le savons tous, sedest très efficace pour rechercher et remplacer la chaîne, par exemple trouver « a » et le remplacer à « 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 sedcommande. Je dois donc utiliser d'autres commandes ou scripts au lieu desed 's/a/b/g'. –


En fait, c'est juste une substitution basée sur une expression régulière. Tout outil ou langage capable de gérer une telle chose sera en mesure de faire la même chose, mais avec diverses syntaxe: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. À côté de cela, de nombreux outils et langues peuvent également remplacer les chaînes de texte brut. Votre question est donc en quelque sorte large.
manatwork

1
Pourquoi? Quel problème essayez-vous de résoudre?
Gilles 'SO- arrête d'être méchant'

Les systèmes linux recadrés pour la télévision n'ont pas de commande sed. Je dois donc utiliser une autre commande ou un autre script au lieu de sed 's / a / b / g'.
binghenzq

Réponses:


12

Oui, il existe différentes façons de procéder. Vous pouvez également utiliser awk, perlou bashpour effectuer ces activités. En général, sedc'est probablement l'outil le plus approprié pour effectuer ce type 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 -icommutateur.

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

Car awkc'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 y est redirigé via ceci:

$ { ... } < data.txt

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


Merci pour votre réponse et je vais l'essayer le jour ouvrable suivant, mais je ne suis pas sûr que cela fonctionne car certaines commandes n'existent peut-être pas dans les systèmes Linux recadrés de télévision, tels que `` sed ''. , 'grep' et ainsi de suite pour le résoudre.
binghenzq

@binghenzq - J'ai ajouté des exemples qui modifient en ligne le fichier.
slm

-1 Je vote rarement en bas, mais dans ce cas, le point de la question semblait être une méthode plus simple plutôt que d'autres plus / également complexes et probablement aussi dépendantes. Si la question portait uniquement sur des alternatives pour une installation complète de la machine * nix, je répondrais probablement +1 à cette bonne réponse.
Michael Durrant

@ MichaelDurrant - Je viens d'ajouter les modifications en ligne élaborées b / c que l'OP leur a demandé. Le PO définit également l'exigence de NE PAS utiliser sedpas I. Sed est l'outil approprié pour effectuer des substitutions comme celle-ci, et il demande évidemment de mieux comprendre les rôles de ces outils, donc montrer à quelqu'un ces choses bien que mauvaises, est extrêmement éducatif en montrant les pourquoi. Trop souvent, le ppl dans le savoir dit simplement «ne le fais pas» sans expliquer pourquoi, je le suis. Mais merci d'avoir au moins laissé un commentaire sur les raisons pour lesquelles vous DV.
slm

Bien sûr, je pensais que c'était une excellente réponse à tous les autres égards. ouais je déteste -1 sans explication.
Michael Durrant

13

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

$ echo "foobar" | tr a b   
foobbr

trest mieux que sedpour cela en fait car utiliser sed(sans parler perlou awk) pour des substitutions d'une seule lettre, c'est comme 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 ksh, zshou la bashsyntaxe:

$ 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.


Existe-t-il une option pour ignorer la casse ${foo//a/b}?
AlikElzin-kilaka

@ AlikElzin-kilaka J'ai bien peur que non. Vous devrez utiliser quelque chose de plus sophistiqué comme, par exemple: echo "$foo" | sed 's/a/b/iou donner une classe de caractères: echo ${foo//[aA]/b}.
terdon

4

Vous pouvez utiliser Vim en mode Ex:

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

  2. s remplacer

  3. g remplacement global

  4. x sauver et fermer


grand merci. juste pour ajouter, l'indicateur -c consiste à exécuter la commande au début de l'édition (puisque ex est un éditeur) et l'indicateur -s est soit le mode script désactivant la rétroaction, soit comme certains aiment dire le mode slient. ref pour plus d'informations: ex-vi.sourceforge.net/ex.html
Jimmy MG Lim

3

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 edde travailler sur chaque ligne (vous pouvez également l'utiliser %, ce qui sera plus familier si vous êtes habitué à vim), et le reste est une recherche et un remplacement standard. wlui dit d'écrire (enregistrer) le fichier, lui qdit de quitter.

Notez que, contrairement à l' -ioption de sed (et aux 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 je n'en sais pas vraiment grand-chose edet je ne serais pas surpris s'il a réellement cette capacité (la philosophie Unix étant ce qu'elle est).


2

En utilisant la commande ancêtre (dans laquelle -ssignifie silencieux (silencieux) et la virgule avant les commandes signifie exécuter sur toutes les lignes):

Il suffit d'imprimer sur STDOUT :

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

remplacement en place:

ed -s file <<!
,s/a/b/g
w
q
!
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.