Her değişiklikten önce, beni onaylamanızı istemek için bir yol var mı? Vim içini değiştirirken 'c' benzeri bir şey.
Sed bunu yapıyor mu?
Her değişiklikten önce, beni onaylamanızı istemek için bir yol var mı? Vim içini değiştirirken 'c' benzeri bir şey.
Sed bunu yapıyor mu?
Yanıtlar:
sed
Etkileşimli bir akış düzenleyicisi olduğu için bunu yapmak muhtemelen mümkün olmazdı. sed
Bir senaryoda sarmalamak çok fazla düşünmeyi gerektirir. Sadece bunu yapmak daha kolaydır vim
:
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' file.in
Aşağıdaki yorumlarda bahsedildiğinden beri, bunun geçerli dizindeki belirli bir dosya adı globbing deseniyle eşleşen birden fazla dosyada nasıl kullanılacağı:
for fname in file*.txt; do
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Veya, dosyayı değiştirmeden önce, dosyanın ilk önce belirli bir kalıpla eşleşen bir satır içerdiğinden emin olmak istiyorsanız,
for fname in file*.txt; do
grep -q 'PATTERN' "$fname" &&
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Yukarıdaki iki kabuk döngüsünde find
, aynı şeyleri yapan komutlar halinde değiştirilmiş, ancak bazı top-dir
dizin içinde veya altında bir yerde belirli bir isme sahip tüm dosyalar için ,
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' {} \;
Veya, orijinal kabuk halkalarını kullanarak ve find
bunlara besleme yol adları koyarak:
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 {} +
Siz, her durumda, ofor filename in $( grep -rl ... )
zamandan beri olduğu gibi bir şey yapmak istemezsiniz.
grep
olduğunu bile döngünün ilk yineleme, başlamadan önce çalışan bitirir inelegant vegrep
, boşluklar üzerindeki kelimelere bölünür ve bu kelimeler dosya isminden geçer (bu, boşluk ve özel karakterler içeren yol adlarını diskalifiye eder).İlgili:
sed
, çoklu dosyalar üzerinde, örneğin sed -i 's/old/new/g' /path/to/*.txt
veya benzer bir şeyde çalışabilmesidir .
for i in $(grep -rl "old"); do vim -c "%s/old/new/gc" -c "wq" "$i"; done
Böyle yaparak elde edebilirsiniz:
:%s/OLD_TEXT/NEW_TEXT/gc
Özellikle, c
üçüncü sınırlayıcıdan sonra ekleme .
'C' seçeneğinin yalnızca Vim'de çalıştığını unutmayın; sed
Komut satırında kullanamazsınız .
sed
.
vim
, bu yüzden bu cevap uygulanabilir; gerçi, açıkça Vim ve sed farklı yetenekleri vardır
sed
Dosyada işini yapmasına izin verebilir ve sonucu, ardından etkileşimli olarak orijinal dosyaya ekleyebileceğiniz geçici bir dosyaya kaydedebilirsiniz sdiff
(bkz. Http://www.gnu.org/software/diffutils/manual/diffutils.html # Davetkar-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
}
Bunu tek bir argümanla beslerseniz - searchandreplace "AAA"
- sadece geçerli dizindeki o dizgiyi arar, fakat onu çift argümanlarla beslerseniz - searchandreplace AAA BBB
- o zaman yukarıdakilere ek olarak, ilkini ikinci satırla değiştirmenizi ister " Her satır için satır.