टेक्स्ट फ़ाइल से कैसे हटाएं, सभी लाइनों में एक विशिष्ट स्ट्रिंग होती है?


जवाबों:


2758

लाइन को हटाने के लिए और आउटपुट को मानक से प्रिंट करने के लिए:

sed '/pattern to match/d' ./infile

फ़ाइल को सीधे संशोधित करने के लिए - बीएसडी sed के साथ काम नहीं करता है:

sed -i '/pattern to match/d' ./infile

वही, लेकिन BSD sed (Mac OS X और FreeBSD) के लिए - GNU sed के साथ काम नहीं करता है:

sed -i '' '/pattern to match/d' ./infile

फ़ाइल को सीधे संशोधित करने के लिए (और बैकअप बनाएं) - BSD और GNU sed के साथ काम करता है:

sed -i.bak '/pattern to match/d' ./infile

13
धन्यवाद, लेकिन यह फ़ाइल से इसे मिटाने के लिए नहीं लगता है, लेकिन बस उस स्ट्रिंग के बिना पाठ फ़ाइल सामग्री को प्रिंट करें।
एक क्लॉकवर्क ऑरेंज

115
@A घड़ी की कल: हाँ, आपको आउटपुट को या तो एक नई फ़ाइल में कुछ इस तरह से बदलना होगा sed '/pattern to match/d' ./infile > ./newfileया यदि आप इन-प्लेस एडिट करना चाहते हैं तो आप -iफ्लैग को जोड़ सकते हैं जैसा कि इन में है sed -i '/pattern to match/d' ./infile। ध्यान दें कि -iध्वज को GNU sed की आवश्यकता है और यह पोर्टेबल नहीं है
SiegeX

16
कुछ स्वाद के लिए sed; sed के "-i" ध्वज को प्रदान करने के लिए एक एक्सटेंशन की आवश्यकता होती है। (जैसे sed -i.backup '/pattern to match/d' ./infile) जो मुझे इन-प्लेस संपादन के साथ मिला।
ऐवेलिस

9
@SiegeX बेहतर अभी तक, sedकिसी भी फाइल की तरह कमांड लागू नहीं करते हैं जो संस्करण-नियंत्रित नहीं हैं।
MatrixFrog

84
मैक ओएस एक्स उपयोगकर्ताओं के लिए एक और ध्यान दें: किसी कारण के लिए, -i ध्वज को पास करने के लिए एक तर्क की आवश्यकता होती है, भले ही यह सिर्फ एक खाली स्ट्रिंग हो, जैसे sed -i '' '/pattern/d' ./infile
जार्जलिंगगुय

629

विशिष्ट स्ट्रिंग के साथ लाइनों को हटाने के कई अन्य तरीके हैं sed:

AWK

awk '!/pattern/' file > temp && mv temp file

रूबी (1.9+)

ruby -i.bak -ne 'print if not /test/' file

पर्ल

perl -ni.bak -e "print unless /pattern/" file

शेल (3.2 और बाद में बैश)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

ग्नू ग्रीप

grep -v "pattern" file > temp && mv temp file

और निश्चित रूप से sed(उलटा मुद्रण वास्तविक विलोपन की तुलना में तेज़ है):

sed -n '/pattern/!p' file

4
कैसे एक पैटर्न के साथ एक विशेष लाइन को हटाने के लिए और इसके ऊपर भी तुरंत लाइन? विभिन्न डेटा के बीच में ऐसी हजारों लाइनों के साथ मेरा जुर्माना है।
oortcloud_domicile

1
ओएस / एक्स पर, शेल भिन्नता अग्रणी स्थानों को संरक्षित नहीं करती है, लेकिन मेरे लिए grep -v भिन्नता अच्छी तरह से काम करती है।
पॉल बेस्टरियन

13
sedउदाहरण के लिए एक अलग व्यवहार कर, यह केवल greps! यह कुछ ऐसा होना चाहिए sed -n -i '/pattern/!p' file
कैसरसोल

8
जब हर लाइन पैटर्न से मेल खाती है, तो grep संस्करण काम नहीं करता है। बेहतर करते हैं: grep -v "pattern" file > temp; mv temp fileयह रिटर्न वैल्यू के आधार पर कुछ अन्य उदाहरणों पर लागू हो सकता है।
क्रिस मेस

1
"उलटा छापना वास्तविक विलोपन से तेज है" - मेरी मशीन पर नहीं (2012 मैकबुक एयर, ओएस एक्स 10.13.2)। फ़ाइल बनाएँ seq -f %f 10000000 >foo.txt:। sed d: time sed -i '' '/6543210/d' foo.txtवास्तविक 0m9.294s। sed! p: time sed -i '' -n '/6543210/!p' foo.txtवास्तविक 0m13.671s (छोटी फाइलों के लिए, अंतर बड़ा है।)
jcsahnwaldt का कहना है कि GoFundMonica

252

आप फ़ाइल में लाइनों को बदलने के लिए sed का उपयोग कर सकते हैं। हालाँकि, यह दूसरी फ़ाइल में व्युत्क्रम के लिए grep का उपयोग करने की तुलना में बहुत धीमा प्रतीत होता है और फिर मूल पर दूसरी फ़ाइल को स्थानांतरित करता है।

जैसे

sed -i '/pattern/d' filename      

या

grep -v "pattern" filename > filename2; mv filename2 filename

वैसे भी मेरी मशीन पर पहले कमांड को 3 गुना अधिक समय लगता है।


19
अपने उत्तर को भी वोट दें, सिर्फ इसलिए कि आपने प्रदर्शन की तुलना करने की कोशिश की है!
अनुराग

4
Grep लाइन के साथ वर्तमान फ़ाइल को अधिलेखित करने के लिए विकल्प देने के लिए +1।
रिहुक

2
दूसरा 'ग्रेप' समाधान बड़ी फ़ाइलों के लिए भी बेहतर है
सिमोस

3
मुझे उत्सुकता है कि प्रदर्शन अंतर क्या होगा अगर यह थाsed '/pattern/d' filename > filename2; mv filename2 filename
पीट

8
(ubuntu / usr / share / dict / words का उपयोग करके) grep और mv: होप्स | sed में जगह: 0.197s | sed और mv: 0.031s
ReactiveRaven

77

GNU के साथ इसे करने का आसान तरीका sed:

sed --in-place '/some string here/d' yourfile

55
दूसरों के लिए एक आसान टिप जो इस प्रश्नोत्तर धागे पर ठोकर खाते हैं और शेल स्क्रिप्टिंग के लिए नए हैं: कमांड लाइन पर एक बार के उपयोग के लिए लघु विकल्प ठीक हैं, लेकिन लंबे विकल्प को स्क्रिप्ट में पसंद किया जाना चाहिए क्योंकि वे अधिक पठनीय हैं।
डेनिस

3
-इन-फ़्लैग फ़्लैग के लिए +1। मुझे परीक्षण करने की आवश्यकता है कि अनुमतियाँ संरक्षित फाइलों पर हैं। (कुछ यूजर स्क्रबिंग करना है।)
बी काय

8
ध्यान दें कि लंबा विकल्प केवल GNU sed पर उपलब्ध है। मैक और बीएसडी उपयोगकर्ताओं को इसे इस तरह से करने के लिए इंस्टॉल करने की आवश्यकता होगी।
मैट

एक और टिप: यदि आपका रेगेक्स मैच नहीं करता है, तो -rविकल्प का प्रयास करें (या -E, आपके संस्करण पर निर्भर करता है)। इस regex अक्षरों से परे का उपयोग सक्षम बनाता है +, ?, {...}और (...)
rjh

यह सही उत्तर है जब आपकी डिस्क में अधिक स्थान नहीं है और आप पाठ को किसी अन्य फ़ाइल में कॉपी नहीं कर सकते हैं। यह आदेश क्या प्रश्न किया गया था?
फेरेराब्रगा

38

आप का उपयोग करने पर विचार कर सकते हैं ex(जो एक मानक यूनिक्स कमांड-आधारित संपादक है):

ex +g/match/d -cwq file

कहाँ पे:

  • +निष्पादित पूर्व कमान ( man ex), उसी के रूप में -cनिष्पादित wq(लिखते हैं और छोड़ें)
  • g/match/d- दिए गए के साथ लाइनों को हटाने के लिए पूर्व कमान match, देखें: जी की शक्ति

उपर्युक्त उदाहरण Unix.SE और POSIX विनिर्देशों के लिएex इस पोस्ट के अनुसार किसी फ़ाइल को इन-प्लेस एडिट करने के लिए एक POSIX-compliant तरीका है ।


अंतर sedयह है कि:

sedएक है एस tream प्रवर्तन निदेशालय itor, न कि एक फ़ाइल संपादक। BashFAQ

जब तक आप गैर-लाभकारी कोड, I / O ओवरहेड और कुछ अन्य बुरे दुष्प्रभावों का आनंद नहीं लेते हैं। तो मूल रूप से कुछ पैरामीटर (जैसे कि इन-प्लेस / -i) गैर-मानक FreeBSD एक्सटेंशन हैं और अन्य ऑपरेटिंग सिस्टम पर उपलब्ध नहीं हो सकते हैं।


5
कि बहुत अच्छा है ... जब मैं कर man exयह मेरे लिए आदमी देता है vim, ऐसा लगता है exvim का हिस्सा है ... अगर मैं के लिए सही है कि साधन पैटर्न सिंटैक्स समझ matchहै vimregex.com जो समान है, लेकिन POSIX और PCRE जायके के लिए अलग है?
एंथ्रोपिक

1
:g है POSIX अनुरूप कुछ के साथ आदेश मामूली अंतर । मुझे लगता है कि पीसीआरई इस पर आधारित था।
kenorb

16

मैं मैक पर इसके साथ संघर्ष कर रहा था। साथ ही, मुझे वैरिएबल रिप्लेसमेंट का उपयोग करने की आवश्यकता है।

इसलिए मैंने इस्तेमाल किया:

sed -i '' "/$pattern/d" $file

जहां $fileफ़ाइल जहां विलोपन जरूरत है और$pattern पैटर्न को हटाने के लिए मिलान किया जा रहा है।

मैंने ''इस टिप्पणी से उठाया

यहाँ ध्यान देने वाली बात दोहरे उद्धरण चिह्नों का उपयोग है "/$pattern/d"। जब हम सिंगल कोट्स का उपयोग करते हैं तो वैरिएबल काम नहीं करेगा।


3
मैक के sedबाद एक पैरामीटर की आवश्यकता होती है -i, इसलिए यदि आप बैकअप नहीं चाहते हैं, तो आपको अभी भी एक खाली स्ट्रिंग जोड़ना होगा:-i ''
wisbucky

शेल उपयोग के लिए sed -i "/$pattern/d" $file। आपके उत्तर के लिए धन्यवाद।
अश्वक जूल

14

मैंने एक फ़ाइल के साथ एक छोटा बेंचमार्क बनाया है जिसमें लगभग 345 000 लाइनें हैं। के साथ जिस तरह से grepलगभग 15 गुना तेजी से लगता हैsed इस मामले में विधि की ।

मैंने LC_ALL = C की सेटिंग के साथ और उसके बिना, दोनों की कोशिश की है, ऐसा नहीं लगता कि यह समय में काफी बदलाव करता है। खोज स्ट्रिंग (CDGA_00004.pdbqt.gz.tar) फ़ाइल के बीच में कहीं है।

यहाँ आदेश और समय हैं:

time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt

real    0m0.711s
user    0m0.179s
sys     0m0.530s

time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt

real    0m0.105s
user    0m0.088s
sys     0m0.016s

time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )

real    0m0.046s
user    0m0.014s
sys     0m0.019s

आप किस प्लेटफार्म पर हैं? आप किस सेड / पर्ल / grep के कौन से संस्करण का उपयोग करते हैं?
हैगेलो

मेरे द्वारा उपयोग किया जाने वाला प्लेटफ़ॉर्म Linux (Gentoo) है। Sed संस्करण GNU sed v 4.2.2 है, perl संस्करण perl 5 (I खिचड़ी भाषा बताता है कि मैंने परीक्षण के समय किस संशोधन का उपयोग किया था), और grep (GNU) संस्करण 3.0 है।
जादाज़िया

14

आप इसका उपयोग भी कर सकते हैं:

 grep -v 'pattern' filename

यहां -vआपके पैटर्न के अलावा केवल प्रिंट होगा (इसका मतलब है कि इनवर्ट मैच)।


मैं एक निर्देशिका में लाइनों को कैसे हटा सकता हूं जिसमें एक विशिष्ट स्ट्रिंग है
namannimmo

13

grepआप ऐसा कर सकते हैं परिणाम के रूप में एक inplace प्राप्त करने के लिए :

echo "$(grep -v "pattern" filename)" >filename

4
यह केवल bashशेल या समान (नहीं tcsh) के लिए अच्छा है ।
बचो


4
perl -i    -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3

पहला कमांड फ़ाइल (ओं) को inplace (-i) को एडिट करता है।

दूसरा कमांड एक ही काम करता है लेकिन मूल फ़ाइल (ओं) को .bk को फ़ाइल नामों (.bk को कुछ भी बदला जा सकता है) में जोड़कर कॉपी या बैकअप रखता है।



2

बस अगर कोई इसे स्ट्रिंग्स के सटीक मैचों के लिए करना चाहता है, तो आप -wपूरे के लिए grep - w में ध्वज का उपयोग कर सकते हैं । उदाहरण के लिए, यदि आप उन पंक्तियों को हटाना चाहते हैं जिनकी संख्या 11 है, लेकिन 111 नंबर वाली पंक्तियों को रखें:

-bash-4.1$ head file
1
11
111

-bash-4.1$ grep -v "11" file
1

-bash-4.1$ grep -w -v "11" file
1
111

-fयदि आप एक साथ कई सटीक पैटर्न को बाहर करना चाहते हैं तो यह ध्वज के साथ भी काम करता है । यदि "ब्लैकलिस्ट" प्रत्येक लाइन पर कई पैटर्न के साथ एक फाइल है जिसे आप "फाइल" से हटाना चाहते हैं:

grep -w -v -f blacklist file

थोड़ा भ्रामक। -w, --word-regexp Select only those lines containing matches that form whole words.बनाम-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
साईं


0

उपचारित पाठ को कंसोल में दिखाने के लिए

cat filename | sed '/text to remove/d' 

एक फ़ाइल में इलाज पाठ को बचाने के लिए

cat filename | sed '/text to remove/d' > newfile

एक मौजूदा फ़ाइल के इलाज के पाठ को जोड़ने के लिए

cat filename | sed '/text to remove/d' >> newfile

पहले से ही इलाज किए गए पाठ का इलाज करने के लिए, इस मामले में जो हटा दिया गया है उसकी अधिक पंक्तियों को हटा दें

cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more

| moreएक समय में एक पेज के मात्रा में पाठ दिखाई देगा।


0

आप अच्छे पुराने उपयोग कर सकते हैं edसंपादित करने के लिए करने के लिए इसी तरह से एक फाइल जवाब है कि का उपयोग करता है ex। इस मामले में बड़ा अंतर यह है कि edइसकी कमांड मानक इनपुट के माध्यम से होती है, न कि कमांड लाइन आर्ग्युमेंट जैसे कि ex। एक स्क्रिप्ट में इसका उपयोग करते समय, इसे समायोजित करने का सामान्य तरीका इसके printfलिए पाइप कमांड का उपयोग करना है:

printf "%s\n" "g/pattern/d" w | ed -s filename

या एक वंशानुगत के साथ:

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