Existe-t-il un moyen de demander à sed de me confirmer avant chaque remplacement? Quelque chose de similaire à 'c' lors de l'utilisation, remplacez à l'intérieur de vim.
Est-ce que Sed fait ça du tout?
Existe-t-il un moyen de demander à sed de me confirmer avant chaque remplacement? Quelque chose de similaire à 'c' lors de l'utilisation, remplacez à l'intérieur de vim.
Est-ce que Sed fait ça du tout?
Réponses:
Le faire avec sed
ne serait probablement pas possible car c'est un éditeur de flux non interactif. Envelopper sed
dans un script nécessiterait beaucoup trop de réflexion. Il est plus facile de le faire simplement avec vim
:
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' file.in
Comme cela a été mentionné dans les commentaires ci-dessous, voici comment cela pourrait être utilisé sur plusieurs fichiers correspondant à un modèle particulier de nom de fichier particulier dans le répertoire actuel:
for fname in file*.txt; do
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Ou, si vous voulez d'abord vous assurer que le fichier contient réellement une ligne qui correspond au modèle donné avant de procéder à la substitution,
for fname in file*.txt; do
grep -q 'PATTERN' "$fname" &&
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Les deux boucles ci-dessus modifiées dans des find
commandes qui font la même chose mais pour tous les fichiers avec un nom particulier quelque part dans ou sous un top-dir
répertoire,
find top-dir -type f -name 'file*.txt' \
-exec vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' {} \;
find top-dir -type f -name 'file*.txt' \
-exec grep -q 'PATTERN' {} \; \
-exec vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' {} \;
Ou, en utilisant les boucles de shell originales et find
en leur donnant des noms de chemin d'accès:
find top-dir -type f -name 'file*.txt' -exec sh -c '
for pathname do
vim -c "%s/PATTERN/REPLACEMENT/gc" -c "wq" "$pathname"
done' sh {} +
find top-dir -type f -name 'file*.txt' -exec sh -c '
for pathname do
grep -q "PATTERN" "$pathname" &&
vim -c "%s/PATTERN/REPLACEMENT/gc" -c "wq" "$pathname"
done' sh {} +
En tout cas, vous ne voulez pas faire quelque chose comme for filename in $( grep -rl ... )
depuis
grep
termine avant même de commencer la première itération de loop, ce qui est inélégant , etgrep
seraient divisés en mots sur des espaces, et ces mots seraient soumis à une annulation de nom de fichier (ce qui disqualifie les noms de chemin contenant des espaces et des caractères spéciaux).En relation:
sed
est qu'il peut fonctionner sur plusieurs fichiers, par exemple, sed -i 's/old/new/g' /path/to/*.txt
ou quelque chose de similaire.
for i in $(grep -rl "old"); do vim -c "%s/old/new/gc" -c "wq" "$i"; done
Vous pouvez l'obtenir en faisant ceci:
:%s/OLD_TEXT/NEW_TEXT/gc
Plus précisément, l'ajout c
du troisième délimiteur.
Notez que l'option 'c' ne fonctionne que dans Vim; vous ne pourrez pas l'utiliser avec sed
la ligne de commande.
sed
.
vim
, donc cette réponse est applicable; bien que, clairement vim et sed aient des capacités différentes
Vous pouvez laisser sed
agir le fichier, puis enregistrer le résultat dans un fichier temporaire que vous pouvez ensuite patcher de manière interactive dans le fichier d'origine à l'aide de sdiff
(voir http://www.gnu.org/software/diffutils/manual/diffutils.html # Invoking-sdiff ):
sed -r 's/something/something_else/g' my_file > tmp_file
sdiff -o my_file -s -d my_file tmp_file
searchandreplace () {
if [ -z $2 ] ; then
realpath * | xargs grep -ins --directories=skip --color=always "$1" | nl -s "."
else
realpath * | xargs grep -ins --directories=skip --color=always "$1" | nl -s "."
exp=$(realpath * | xargs grep -ins --directories=skip --color=never "$1" | cut -d':' -f1,2 | awk -F':' '{print $2 $1}' | sed -E "s|^[0-9]+|sed -i \'&s/|; s|//|/"$1"/"$2"/g\' /|")
IFS=$'\n'
for d in $exp
do
read -p "Exec $(echo -e -n "\033[1;31m$d\033[0m")? " -e REP
if [ "$REP" = y ]; then
echo `bash -c $d`;
fi
done
fi
}
Si vous alimentez cela avec un seul argument - searchandreplace "AAA"
- il ne recherche que cette chaîne dans le répertoire en cours, mais si vous le nourrissez avec un double argument - searchandreplace AAA BBB
-, en plus de ce qui précède, il vous demande également de remplacer le premier par le deuxième "ligne par ligne "pour chaque ligne.