Her değişiklikten önce, onay isteyin mi?


37

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?


3
Teknik olarak mümkün ancak yararlı bir çabadan ziyade entelektüel bir alıştırma olacaktır. Bkz büyük klasör hiyerarşisinde bir metin değiştirme yapmak nasıl? hangi Vim ve Perl çözümleri var.
Gilles 'SO- kötülük'

Ben am a 'basit' yol vim (args ve argdo) kullanılarak Ben 'onay' ihtiyaç olduğunda, ama olmadığını merak
Yuvi

1
Bir akış üzerinde düzenlemeyi otomatikleştirmek için sed - temel amacına aykırıdır.
17’de

@teppic gerçekten değil çünkü hala sed'in sizin için yapabileceği metin dosyalarındaki örnekleri bulmanız gerekecek . Sanırım soru bir anlam ifade etmiyor, listeye yanlış dosyalar eklediyseniz ve hangi dosyayı
Kolob Canyon

Yanıtlar:


37

sedEtkileşimli bir akış düzenleyicisi olduğu için bunu yapmak muhtemelen mümkün olmazdı. sedBir 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-dirdizin 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 findbunlara 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.

  1. o gerektirecektir grepolduğunu bile döngünün ilk yineleme, başlamadan önce çalışan bitirir inelegant ve
  2. döndürülen yol adları grep, 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:


2
Bunun avantajı sed, çoklu dosyalar üzerinde, örneğin sed -i 's/old/new/g' /path/to/*.txtveya benzer bir şeyde çalışabilmesidir .
user1717828

10
for i in $(grep -rl "old"); do vim -c "%s/old/new/gc" -c "wq" "$i"; done
tcpaiva

@tecepe, lütfen cevaba dönüştür, Teşekkürler.
Nishant

1
@Nishant Adında veya yolunda boşluk içeren herhangi bir dosyayı diskalifiye ettiği için kırılgan bir cevap olurdu.
Kusalananda

7

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; sedKomut satırında kullanamazsınız .


4
Açıklığa kavuşturmak için: bu normal komut satırında değil, sadece Vim'de çalışır sed.
Brendan,

OP ile etiketlendi vim, bu yüzden bu cevap uygulanabilir; gerçi, açıkça Vim ve sed farklı yetenekleri vardır
ILMostro_7


-1
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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.