sed: फाइलों के एक सेट से पथों की सूची हटाना


0

मेरे पास एक फाइल है जिसका नाम है common.txt जिसमें निरपेक्ष रास्तों की सूची शामिल है। उदाहरण के लिए:

/etc
/etc/group
/var/log/syslog

मेरे पास फाइलों का एक सेट भी है & LT; होस्ट नाम & gt; .txt इसमें निरपेक्ष रास्तों की सूची भी शामिल है। यहाँ एक उदाहरण है (इसे कॉल करें host1.txt ):

/root/.bashrc
/var/log/syslog
/etc/hosts
/bin/true
/etc
/sbin/rtmon
/etc/group

मैं हर उस रास्ते को हटाना चाहूंगा जो सामने आता है common.txt फ़ाइलों के सेट में हर फ़ाइल से & LT; फ़ाइल नाम & gt; .txt । तो, उदाहरण फ़ाइल host1.txt ऊपर बन जाएगा:

/root/.bashrc
/etc/hosts
/bin/true
/sbin/rtmon

मैंने ऐसा करने के लिए निम्नलिखित बैश स्क्रिप्ट लिखी है:

#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

while read -r ONE_PATH
do
   for ONE_FILE in host1.txt host2.txt host3.txt
   do
      sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE"
   done
done < common.txt

मुझे एक मुश्किल समय मिल रहा है ताकि सही सेड कमांड मिल सके। खाली होने पर संचालित सभी फाइलों में परिणाम ऊपर दिखाया गया है।

अपने लक्ष्य को पूरा करने के लिए मैं इसे कैसे ठीक कर सकता हूं?


1
का उत्पादन grep -v -f common.txt somefile.txt की सामग्री है somefile.txt बिना किसी लाइन के जिसमें एक लाइन होती है common.txt
xenoid

क्या आप दोनों फ़ाइलों का एक नमूना प्रदान कर सकते हैं और परिणाम आप देखना चाहते हैं? बस इतना है कि मैं अपने जवाब का परीक्षण कर सकता हूं।
Gerard H. Pille

मैंने भविष्य के पाठकों के लिए धागा बढ़ाने के लिए अनुरोधित उदाहरण प्रदान किया है, लेकिन मुझे अभी तक आपके संशोधित समाधान की कोशिश करने का मौका नहीं मिला है।
Dave

का आउटपुट क्या है sed '\:^/etc$:d' host1.txt? यदि कोई। नीचे दवे के उत्तर में एक बिंदु है। common.txt है /etc, उस लाइन के कारण /etc/hosts host1.txt से भी हटा दिया जाएगा, sed इसमें शामिल सभी लाइनें हटा दी जाएंगी /etc अपने पते के अनुसार। इससे बचने के लिए लंगर लगाएं।
Paulo

जवाबों:


1
#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

declare -r SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
declare -r FILES_DIR=${SCRIPT_DIR%/*}

while read -r ONE_PATH
do
   for ONE_FILE in $(find "$FILES_DIR" -maxdepth 1 -type f -print)
   do
      if [[ "$ONE_FILE" == *".swp" ]] ||
         [[ "$ONE_FILE" == *"common.txt" ]]; then
         continue
      fi

      sed -i '\|^'"$ONE_PATH"'$|d' "$ONE_FILE"
   done

echo "Done removing $ONE_PATH"
done < "$SCRIPT_DIR"/../common.txt

exit 0

0

क्या मुझे ऐसा समाधान सुझाना चाहिए जो sed का उपयोग न करे?

sort common.txt > common.txt.sorted
for f in host1.txt host2.txt host3.txt ; do
    sort $f > $f.sorted
    diff common.txt.sorted $f.sorted | egrep '^>' | sed -e 's/^> //' > $f.output
    rm $f.sorted
done

तरह वर्णानुक्रम में क्रमबद्ध सूची। diff एक फ़ाइल और के बीच अंतर पाता है common.txt egrep उन पंक्तियों को चुनता है जो इसके साथ शुरू होती हैं >, जो लाइनों में हैं host1.txt.sorted लेकिन में नहीं common.txt.sorted । आखिरकार, एसईडी अग्रणी निकालता है > (कि & gt; एक स्थान के बाद) द्वारा जोड़ा गया diff

आउटपुट सूची वर्णमाला क्रम में भी होगी।


-1

पहले इनपुट को रिवर्स में सॉर्ट किया जाना चाहिए। यह हटाने / आदि का कोई फायदा नहीं है और फिर / etc / group की तलाश में है। तब हम सत्यापित करते हैं कि क्या फ़ाइल को लिखा जा सकता है (यदि छोड़ें नहीं)। तब ONE_PATH बच जाना चाहिए और फिर sed अपना काम कर सकता है,

sort -r common.txt \
| while read -r ONE_PATH
do
   for ONE_FILE in host1.txt host2.txt host3.txt
   do
      if [ -w "$ONE_FILE" ]
      then
        # sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE"
        ONE_PATH_ESC=$(echo "$ONE_PATH" | sed "s!/!\\\/!g")
        sed -i 's/^'"$ONE_PATH_ESC"'//' "$ONE_FILE"
      fi
   done
done

प्रदान किए गए परीक्षण डेटा के साथ, आपको मिलता है:

$ pr -n host1.txt
1   /root/.bashrc
2
3   /hosts
4   /bin/true
5
6   /sbin/rtmon
7

3 खाली लाइनें हैं।


आपने इसका परीक्षण नहीं किया है, क्या आपके पास है?
Scott

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