2017-10-08 6 views
2

Je souhaite remplacer toutes les barres obliques '/' par des barres obliques inverses '\' et vice versa.Remplacer un caractère par un autre et vice versa dans une chaîne

Ma solution naïve est de le faire avec tr mais je besoin d'un caractère d'espace réservé, que je ne pense pas est très joli:

tr '/' '¢' | tr '\\' '/' | tr '¢' '\\' 

et cela fonctionne aussi que tant qu'il ne semble une '¢' dans ma contribution, ce qui dans mon cas est probablement assez - mais bon, qui sait? Bien sûr, il est facile de prendre cette même idée et de la rendre plus robuste en utilisant sed, puis de remplacer «¢» par une chaîne arbitrairement aléatoire - comme «½ | # & ¬_ $» ou quelque chose comme ça. Mais je voulais savoir s'il y avait une seule commande bash pour y parvenir, ce qui rendrait cette chose plus courte, plus lisible et plus robuste. Peut-être sed peut le faire hors de la boîte?


Pendant que nous y sommes, quel est le nom correct pour cette opération? Comme "remplacer bidirectionnel". Si je savais que mes recherches google auraient probablement été plus fructueuses. J'ai aussi essayé de «changer de personnage», mais je n'ai trouvé que des remplacements réguliers.

Répondre

5

Vous n'avez pas besoin d'un caractère intermédiaire car tr ne traverse qu'une seule fois la chaîne et, par conséquent, un caractère ne sera jamais remplacé plus d'une fois. La commande suivante tr devrait le faire:

tr '/\' '\\/' <<< '//\\ then \\// and/and finally a \ in the string' 

cède

\\// then //\\ and \ and finally a/in the string 

Ou, plus simplement:

tr ab ba <<< "ab ba bb aa" # yields "ba ab aa bb" 

Vous pouvez également utiliser sed:

sed 'y#/\\#\\/#' <<< '//\\ then \\// and/and finally a \ in the string' 

yi

champs
\\// then //\\ and \ and finally a/in the string 

De man sed:

[2addr] y/chaine1/chaine2/

remplacer toutes les occurrences de caractères string1 dans l'espace de motif avec les caractères correspondants de chaine2. N'importe quel caractère autre qu'un backslash ou une nouvelle ligne peut être utilisé à la place d'une barre oblique pour délimiter les chaînes. Dans string1 et string2, un backslash suivi d'un «n» est remplacé par un caractère de nouvelle ligne. Une barre oblique inverse est remplacée par une barre oblique inversée. Enfin, une barre oblique inversée suivie de tout autre caractère (sauf un saut de ligne) est ce caractère littéral.

+2

Merci! Peut-être que vous pouvez ajouter là-dedans que la chose la plus générale (que j'ai appris de ceci) est: avec 'tr' le remplacement se produit par élément. Dans 'tr ab xy' 'a' est remplacé par 'x' et 'b' est remplacé par 'y', et donc' tr ab ba' remplacera 'a' par 'b' et vice versa. C'était la chose la plus générale qui me manquait à propos de 'tr'. L'exemple avec les barres obliques inverses est un peu malheureux, à cause de l'échappement, ce qui n'était vraiment pas mon point de vue et le type d'encombrement de la question (et par conséquent les réponses). – dingalapadum

+1

Si vous éditez votre réponse et ajoutez les choses mentionnées ci-dessus, je serai heureux de l'accepter (demain) - cela correspondrait aussi mieux au titre. Btw. J'aime la modification – dingalapadum

1
tr \\\\/ /\\\\ 

Entrée:

//fgdf\\ 

sortie:

\\fgdf// 

Pourquoi 4 antislashs? Deux barres obliques inverses font un backslash dans la coque, donc tr reçoit \\/ et /\\. Il a ses propres séquences de barre oblique inverse, ainsi il interprète deux antislashs comme un backshash.

+2

La réponse correcte à votre question de 'Pourquoi 4 barres obliques inverses? 'Est' Parce que je n'ai pas cité mes chaînes correctement'. Utilisez toujours des guillemets doubles pour exécuter une tâche spécifique (par exemple, extension de variable), puis utilisez toujours des guillemets doubles, sauf si vous n'avez PAS BESOIN de guillemets pour effectuer une tâche spécifique (par exemple expansion générique). –

+0

Les guillemets ne valent pas mieux que les guillemets, ne simplifient pas l'expression et n'ajoutent rien. – user31264

+0

M. Morton vient de me rattraper, essayant d'ajouter un commentaire négatif dans n'importe quelle réponse. Ce gars est très actif dans mes réponses, ayant probablement quelque chose contre moi. – user31264