Shell : remplacer un long texte par un autre

gnu1 -  
dubcek Messages postés 18789 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour,
Je fais appel à vous car je n'arrive pas à trouver la bonne méthode pour ce que j'ai besoin de faire :
.
En shell/bash, je cherche à remplacer dans un fichier texte une longue chaine de caractères (5000 à 10000 caractères) par une autre de taille à peu près similaire.
.
sed me parait inapproprié pour ce que je veux faire, en particulier parcequ'il va interpréter mon texte à rechercher comme une expression régulière. Mais j'ai aussi l'impression que ça n'a pas été prévu pour remplacer de très grosses chaines de caractères par d'autres.
.
Ce que j'ai pour l'instant :
- un gros fichier texte fichier.txt
- dans une variable $recherche j'ai mis la chaine de caractères qui est à rechercher et à remplacer (multiligne et avec toutes sortes de caractères comme parenthèses crochets ... etc dedans)
- dans une variable $valeur j'ai mis la chaine de caractères qui devra remplacer $recherche dans le fichier
.
Comment vous y prendriez-vous pour faire cela ?
Merci d'avance
A voir également:

3 réponses

dubcek Messages postés 18789 Date d'inscription   Statut Contributeur Dernière intervention   5 637
 
hello
pour autant qu'il n'y ait pas de \Q\E ni # dans le texte
on peut remplacer # par n'importe quel autre car. pas dans la variable
\Q ignore les car. spéciaux jusqu'à \E
 perl -pe   "s#\Q${var}\E#replace#"
0
gnu1
 
Salut, merci pour ta réponse
.
En fait oui je cherche une solution générale, mes variables pouvant contenir tous les caractères "texte" possibles (ascii de 32 à 126).
Il n'y a pas de commande qui fasse la même chose que sed sans utiliser d'expression régulière ?
.
0
dubcek Messages postés 18789 Date d'inscription   Statut Contributeur Dernière intervention   5 637
 
j'en vois pas, le but des ces commandes étant justement les regex
si on remplace les / par \/ dans la variable, essayer
perl -pe "s/\Q${var//\//\\/}\E/replace/"

sinon en shell, si il y a moyen d'isoler le texte à remplacer
0
gnu1
 
D'accord, dommage
.
J'ai une autre question alors (pas forcément en rapport avec ce sujet) :
Est-ce qu'il existe un outil en ligne de commande pour travailler sur des fichiers
- par exemple rechercher une chaine, supprimer une chaine, remplacer une chaine/regex , tronquer, ... -
mais qui travaille par flux et non pas ligne par ligne ?

grep/sed c'est bien, mais quand on ne cherche à faire du multiligne... ça n'a pas l'air prévu pour. Il n'y aurait pas un outil simple qui fasse ça simplement, a votre connaissance ?
merci
0
dubcek Messages postés 18789 Date d'inscription   Statut Contributeur Dernière intervention   5 637
 
sed veut dire stream editor ....
montre un exemple précis de ce que tu veux faire
sed grep awk traitent des fichiers textes, c'est pour ca que la ligne est l'élément de base, mais on peut quasiment tout faire, par ex : commande ¦ sed -e xxx
0
gnu1
 
Un exemple de ce que je veux maintenant faire :
fic1 est un fichier binaire de 600ko
fic2 est un autre fichier binaire de 800ko
ficB est un fichier binaire de 76Mo
.
Dans le fichier ficB, il y a quelque part le contenu du fichier fic1.
.
Je voudrais remplacer, à l'intérieur de ficB, la portion correspondante à fic1 par le contenu du fichier fic2
En shell/bash :-)
0
dubcek Messages postés 18789 Date d'inscription   Statut Contributeur Dernière intervention   5 637
 
avec xxd, on peut convertir les fichiers en hexa, donc en texte, faire la substitution avec sed, par ex. et reconvertir en binaire toujours avec xxd
par ex.
xxd -p -c 1 fic > fic2  # convertit fic en hexa, 1 octet par ligne
xxd -p -r fic2 > fic3 # reconvertit en binaire
0
gnu1
 
Intéressant merci, je vais essayer ça, idéalement en mettant tout sur la même ligne pour que le sed soit plus facile
.
Sinon je commençais à envisager une solution peut être en Perl ou en C avec buffer de la taille de la chaine recherchée pour ensuite me placer octet par octet sur le gros fichier et comparer, et une fois la chaine localisée, reconstruire le fichier avec la nouvelle chaine, mais si je peux éviter ... merci !
0
dubcek Messages postés 18789 Date d'inscription   Statut Contributeur Dernière intervention   5 637
 
ce teste fonctionne avec du texte mouliné par xxd, ca doit fonctionner avec du binaire; on change dans ficB madame (contenu dans fic1) par monsieur (contenu dans fic2)
$ head fic*
==> fic1 <==
madame
==> fic2 <==
monsieur
==> ficB <==
bonjour madame comment ca va
$ xxd -c 1 -p ficB | awk -v z1="$(xxd -c 1 -p fic1)" -v z2="$(xxd -c 1 -p fic2)" 'BEGIN {RS=""} {sub(z1, z2);print}'| xxd -r -p > ficC
$ cat ficC
bonjour monsieur comment ca va

- si fic1 ou fic2 sont du texte, la dernière ligne peut être un \n qu'il faut enlever
- je passe par des variables (z1 z2), à voir si la taille de fic1 ou fic2 n'est pas un problème
- si le binaire est un exécutable, pas sûr qu'il fonctionne après si la taille a changé
0