Apakah ada cara untuk membuat saya meminta konfirmasi sebelum setiap penggantian? Sesuatu yang mirip dengan 'c' saat menggunakan ganti inside vim.
Apakah sed melakukan ini sama sekali?
Apakah ada cara untuk membuat saya meminta konfirmasi sebelum setiap penggantian? Sesuatu yang mirip dengan 'c' saat menggunakan ganti inside vim.
Apakah sed melakukan ini sama sekali?
Jawaban:
Melakukannya dengan sed
mungkin tidak akan mungkin karena itu adalah editor aliran non-interaktif. Membungkus sed
naskah akan membutuhkan pemikiran terlalu banyak. Lebih mudah melakukannya dengan vim
:
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' file.in
Karena disebutkan dalam komentar di bawah, inilah cara ini akan digunakan pada banyak file yang cocok dengan pola globbing nama file tertentu di direktori saat ini:
for fname in file*.txt; do
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Atau, jika Anda pertama kali ingin memastikan bahwa file tersebut benar-benar berisi garis yang cocok dengan pola yang diberikan terlebih dahulu, sebelum melakukan penggantian,
for fname in file*.txt; do
grep -q 'PATTERN' "$fname" &&
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Dua loop shell di atas diubah menjadi find
perintah yang melakukan hal yang sama tetapi untuk semua file dengan nama tertentu di suatu tempat di dalam atau di bawah beberapa top-dir
direktori,
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' {} \;
Atau, menggunakan loop shell asli dan find
memasukkan nama path ke dalamnya:
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 {} +
Bagaimanapun, Anda tidak ingin melakukan sesuatu seperti for filename in $( grep -rl ... )
itu
grep
selesai berjalan bahkan sebelum memulai iterasi pertama dari loop, yang tidak elegan , dangrep
akan dibagi menjadi kata-kata di spasi putih, dan kata-kata ini akan mengalami globbing nama file (ini mendiskualifikasi nama path yang berisi spasi dan karakter khusus).Terkait:
sed
adalah dapat beroperasi pada banyak file, misalnya, sed -i 's/old/new/g' /path/to/*.txt
atau sesuatu yang serupa.
for i in $(grep -rl "old"); do vim -c "%s/old/new/gc" -c "wq" "$i"; done
Anda bisa mendapatkan ini dengan melakukan seperti:
:%s/OLD_TEXT/NEW_TEXT/gc
Secara khusus, menambahkan c
pembatas setelah ketiga.
Perhatikan bahwa opsi 'c' hanya berfungsi di Vim; Anda tidak akan dapat menggunakannya dengan sed
di baris perintah.
sed
.
vim
, sehingga jawaban ini berlaku; meskipun, jelas vim dan sed memiliki kemampuan yang berbeda
Anda dapat membiarkannya sed
melakukan hal tersebut pada file dan kemudian menyimpan hasilnya ke file sementara yang kemudian dapat Anda tempel secara interaktif ke dalam file asli menggunakan sdiff
(lihat 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
}
Jika Anda memberi makan ini dengan argumen tunggal - searchandreplace "AAA"
- itu hanya mencari string itu di direktori saat ini, tetapi jika Anda memberi makan dengan argumen ganda - searchandreplace AAA BBB
- maka di samping itu juga meminta Anda untuk mengganti yang pertama dengan yang kedua "baris oleh baris "untuk setiap baris.