Je dois remplacer un texte dans un fichier texte par un autre. D'habitude je ferais quelque chose comme
sed -i 's/text/replacement/g' path/to/the/file
Le problème est que text
et replacement
sont des chaînes complexes contenant des tirets, des barres obliques, des barres obliques, des guillemets, etc. Si j'échappe à tous les caractères nécessaires dans text
, cela devient rapidement illisible. D'autre part, je n'ai pas besoin de la puissance des expressions régulières: je dois juste remplacer le texte littéralement.
Y a-t-il un moyen de faire la substitution de texte sans en utilisant des expressions régulières avec une commande bash?
Il serait assez trivial d’écrire un script qui le fasse, mais j’imagine qu’il devrait déjà exister quelque chose.
Lorsque vous n'avez pas besoin du pouvoir des expressions régulières, ne l'utilisez pas. C'est bon.
Mais ce n’est pas vraiment une expression régulière .
sed 's|literal_pattern|replacement_string|g'
Donc, si /
est votre problème, utilisez |
et vous n'avez pas besoin d'échapper à l'ancien.
ps: à propos des commentaires, voir aussi cette réponse de Stackoverflow sur Échappe une chaîne pour le modèle de recherche sed .
Mise à jour: Si vous utilisez Perl , essayez-le avec \Q
et \E
comme ceci,Perl -pe 's|\Qliteral_pattern\E|replacement_string|g'
RedGrittyBrick
a également suggéré une astuce similaire avec la syntaxe Perl plus forte dans un commentaire ici
export FIND='find this'
export REPLACE='replace with this'
Ruby -p -i -e "gsub(ENV['FIND'], ENV['REPLACE'])" path/to/file
C'est la seule solution 100% sûre ici, car:
sed
)}
char (donc supérieure à une solution Perl soumise)ENV['FIND']
est utilisé, pas $FIND
. Avec $FIND
ou votre texte inséré dans le code Ruby, vous risquez de rencontrer une erreur de syntaxe si votre chaîne contient un '
non échappé.La commande replace
le fera.
https://linux.die.net/man/1/replace
Changement de lieu:
replace text replacement -- path/to/the/file
Pour stdout:
replace text replacement < path/to/the/file
Exemple:
$ replace '.*' '[^a-z ]{1,3}' <<EOF
> r1: /.*/g
> r2: /.*/gi
> EOF
r1: /[^a-z ]{1,3}/g
r2: /[^a-z ]{1,3}/gi
La commande replace
est fournie avec MySQL ou MariaDB.
Vous pouvez également utiliser le mécanisme \Q
de Perl pour " citer des métacaractères de modèle "
Perl -pe 'BEGIN {$text = q{your */text/?goes"here"}} s/\Q$text\E/replacement/g'
découvrez mon script Perl. il fait exactement ce dont vous avez besoin sans utilisation implicite ou explicite d’expression régulière:
https://github.com/Samer-Al-iraqi/Linux-str_replace
str_replace Search Replace File # replace in File in place
STDIN | str_replace Search Replace # to STDOUT
très pratique non? J'ai dû apprendre à Perl pour le faire. parce que j'en ai vraiment besoin.
Vous pouvez le faire en en échappant vos patterns. Comme ça:
keyword_raw='1/2/3'
keyword_regexp="$(printf '%s' "$keyword_raw" | sed -e 's/[]\/$*.^|[]/\\&/g')"
# keyword_regexp is now '1\/2\/3'
replacement_raw='2/3/4'
replacement_regexp="$(printf '%s' "$replacement_raw" | sed -e 's/[\/&]/\\&/g')"
# replacement_regexp is now '2\/3\/4'
echo 'a/b/c/1/2/3/d/e/f' | sed -e "s/$keyword_regexp/$replacement_regexp/"
# the last command will print 'a/b/c/2/3/4/d/e/f'
Les crédits pour ces solutions vont ici: https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
Note1: cela ne fonctionne que pour les mots-clés non vides. Sed (sed -e 's//replacement/'
) n'accepte pas les mots clés vides.
Note2: malheureusement, je ne connais pas d'outil populaire qui n'utiliserait PAS regexp-s pour résoudre le problème. Vous pouvez écrire un tel outil en Rust ou en C, mais ce n’est pas là par défaut.
Vous pouvez utiliser php's str_replace :
php -R 'echo str_replace("\|!£$%&/()=?^\"'\''","replace",$argn),PHP_EOL;'<input.txt >output.txt
Remarque: Toutefois, vous devrez toujours échapper les guillemets simples '
et les guillemets doubles "
.
J'ai rassemblé quelques autres réponses et proposé ceci:
function unregex {
# This is a function because dealing with quotes is a pain.
# http://stackoverflow.com/a/2705678/120999
sed -e 's/[]\/()$*.^|[]/\\&/g' <<< "$1"
}
function fsed {
local find=$(unregex "$1")
local replace=$(unregex "$2")
shift 2
# sed -i is only supported in GNU sed.
#sed -i "s/$find/$replace/g" "$@"
Perl -p -i -e "s/$find/$replace/g" "$@"
}
Node.JS équivalent de @Nowaker:
export FNAME='moo.txt'
export FIND='search'
export REPLACE='rpl'
node -e 'fs=require("fs");fs.readFile(process.env.FNAME,"utf8",(err,data)=>{if(err!=null)throw err;fs.writeFile(process.env.FNAME,data.replace(process.env.FIND,process.env.REPLACE),"utf8",e=>{if(e!=null)throw e;});});'