प्रत्येक प्रतिस्थापन से पहले पुष्टि के लिए sed पूछें?


37

क्या प्रत्येक को बदलने से पहले मुझे पुछने के लिए सीक बनाने का कोई तरीका है? अंदर की जगह का उपयोग करते समय 'ग' के समान कुछ।

क्या sed यह सब करता है?


3
यह तकनीकी रूप से संभव होगा लेकिन एक उपयोगी प्रयास की तुलना में एक बौद्धिक अभ्यास का अधिक। बड़े फ़ोल्डर पदानुक्रम में पाठ प्रतिस्थापन कैसे करें देखें ? जिसमें विम और पर्ल समाधान हैं।
गिल्स एसओ- बुराई को रोकें '

मैं कर रहा हूँ vim (args और argdo) का उपयोग कर जब भी मैं 'पुष्टि' की जरूरत है, लेकिन अगर वहाँ था सोच रहा था एक 'सरल' रास्ता
युवी

1
यह sed के मूल उद्देश्य के खिलाफ जाता है - एक स्ट्रीम पर संपादन को स्वचालित करने के लिए।
टेपरिक

@teppic वास्तव में नहीं है क्योंकि आपको अभी भी पाठ फ़ाइलों में ऐसे उदाहरण खोजने होंगे , जो आपके लिए sed कर सकते हैं। मुझे लगता है कि सवाल समझ में आता है, बस अगर आपने गलत फाइलों को एक सूची में जोड़ दिया है और यह देखना चाहता है कि आप किस फाइल का संपादन कर रहे थे
Kolob Canyon

जवाबों:


37

इसके साथ ऐसा करना sedसंभव नहीं होगा क्योंकि यह एक गैर-संवादात्मक स्ट्रीम संपादक है। sedएक स्क्रिप्ट में लपेटकर बहुत अधिक सोच की आवश्यकता होगी। यह सिर्फ इसके साथ करना आसान है vim:

vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' file.in

चूंकि यह नीचे टिप्पणियों में उल्लेख किया गया था, यहां यह बताया गया है कि वर्तमान फ़ाइलों में एक विशेष फ़ाइल नाम ग्लोबिंग पैटर्न से मेल खाने वाली कई फ़ाइलों पर इसका उपयोग कैसे किया जाएगा:

for fname in file*.txt; do
    vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done

या, यदि आप पहले यह सुनिश्चित करना चाहते हैं कि फ़ाइल में वास्तव में एक पंक्ति है जो दिए गए पैटर्न से मेल खाती है, तो प्रतिस्थापन करने से पहले,

for fname in file*.txt; do
    grep -q 'PATTERN' "$fname" &&
    vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done

उपरोक्त दो शेल लूप findकमांड में संशोधित किए गए हैं जो समान चीजें करते हैं लेकिन सभी फाइलों के लिए एक विशेष नाम के साथ कहीं या कुछ top-dirनिर्देशिका में,

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' {} \;

या, मूल शेल छोरों का उपयोग करके और findउन में फ़ीड पथनाम रखने के लिए:

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 {} +

आप करते हैं, किसी भी मामले में, नहीं की तरह कुछ करना चाहता हूँ for filename in $( grep -rl ... )के बाद से

  1. इसके लिए आवश्यक है कि grepलूप के पहले पुनरावृत्ति को शुरू करने से पहले खत्म होने वाले रनिंग, जो कि अयोग्य हो , और
  2. द्वारा भेजे गए पथनाम को व्हाट्सएप grepपर शब्दों में विभाजित किया जाएगा, और ये शब्द फिल्नाम ग्लोबबिंग से गुजरेंगे (यह उन नामों को अयोग्य बनाता है जिनमें रिक्त स्थान और विशेष वर्ण हैं)।

सम्बंधित:


2
इसका फायदा sedयह है कि यह कई फाइलों, जैसे, sed -i 's/old/new/g' /path/to/*.txtया कुछ समान पर काम कर सकता है ।
user1717828

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

@tecepe, कृपया इसे उत्तर में बदलें, थैंक यू।
निशांत

1
@ निशांत यह एक नाजुक जवाब होगा क्योंकि यह अपने नाम या रास्ते में व्हाट्सएप युक्त किसी भी फाइल को अयोग्य घोषित करेगा।
Kusalananda

7

आप ऐसा करके प्राप्त कर सकते हैं:

:%s/OLD_TEXT/NEW_TEXT/gc

विशेष रूप से, cतीसरे परिसीमन के बाद जोड़ना ।

ध्यान दें कि 'c' विकल्प केवल Vim में काम करता है; आप sedकमांड लाइन पर इसका उपयोग नहीं कर पाएंगे ।


4
स्पष्ट करने के लिए: यह केवल Vim में काम करता है, न कि नियमित कमांड लाइन में sed
ब्रेंडन

ओपी के साथ टैग किया गया है vim, इसलिए यह उत्तर लागू है; हालाँकि, स्पष्ट रूप से विम और
सेड की

4

आप sedफ़ाइल पर अपना काम कर सकते हैं और फिर परिणाम को एक अस्थायी फ़ाइल में सहेज सकते हैं, जिसे आप तब उपयोग कर मूल फ़ाइल में पैच कर सकते sdiffहैं (देखें http://www.gnu.org/software/diffutils/manual/diffutils.html # चालान-एसडीएफ ):

sed -r 's/something/something_else/g' my_file > tmp_file
sdiff -o my_file -s -d my_file tmp_file

-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
}

यदि आप searchandreplace "AAA"इसे एकल तर्क के साथ खिलाते हैं - - यह केवल वर्तमान निर्देशिका में उस स्ट्रिंग को खोजता है, लेकिन यदि आप इसे दोहरे तर्कों के साथ फ़ीड करते हैं - searchandreplace AAA BBB- तो उपरोक्त के अलावा यह आपको दूसरी "लाइन" के साथ पहले को बदलने के लिए भी कहता है। लाइन "हर लाइन के लिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.