Sed का उपयोग करके किसी पाठ फ़ाइल से विशिष्ट लाइन नंबर (s) हटाएं?


235

मैं एक या एक से अधिक विशिष्ट पंक्ति संख्याओं को फ़ाइल से हटाना चाहता हूं। मैं इसे सेड का उपयोग कैसे करूँगा?


1
क्या आप जो चाहते हैं उसका अधिक विशिष्ट उदाहरण दे सकते हैं? आप कैसे तय करेंगे कि किस लाइन को हटाना है?
मार्क बायर्स

शायद यह भी देखें stackoverflow.com/questions/13272717/… और सिर्फ रिवर्स में लागू करें (प्रिंट करें यदि कुंजी साहचर्य सरणी में नहीं है)।
त्रिकोणीय

जवाबों:


374

यदि आप लाइनों को 10 और 12 के माध्यम से हटाना चाहते हैं:

sed -e '5,10d;12d' file

यह स्क्रीन पर परिणाम प्रिंट करेगा। यदि आप परिणाम को उसी फ़ाइल में सहेजना चाहते हैं:

sed -i.bak -e '5,10d;12d' file

यह फ़ाइल को वापस कर देगा file.bak, और दी गई लाइनों को हटा देगा।

नोट: लाइन नंबर 1 से शुरू होते हैं। फ़ाइल की पहली पंक्ति 1 है, 0 नहीं।


32
सभी यूनिक्स में "-i" के साथ ग्नू सेड नहीं है। "Sed cmd file> file" पर वापस गिरने की गलती न करें, जो आपकी फ़ाइल को मिटा देगा।
Pra

4
क्या होगा अगर मैं 5 वीं पंक्ति को अंतिम पंक्ति तक हटाना चाहता था?
जुरगेन पॉल

14
@EaretheWorldsed -e '5,$d' file
ब्रायन कैंपबेल

1
@BrianCampbell मुझे केवल एक विशेष लाइन को हटाने के लिए क्या करना चाहिए ??
काणागावेलु सुगुमार

14
@ कनगावेलुसुगुमर sed -e '5d' file। वाक्य रचना है <address><command>; जहाँ <address>या तो एक लाइन हो सकती है जैसे 5या लाइनों की एक श्रृंखला 5,10, और कमांड dदी गई लाइन या लाइनों को हटा देती है। पते भी नियमित अभिव्यक्ति हो सकते हैं, या डॉलर चिह्न $फ़ाइल की अंतिम पंक्ति को दर्शाता है।
ब्रायन कैंपबेल

50

आप किसी विशेष सिंगल लाइन को उसके लाइन नंबर से हटा सकते हैं

sed -i '33d' file

यह 33 लाइन नंबर पर लाइन को हटा देगा और अपडेट की गई फ़ाइल को बचाएगा।


1
मेरे मामले में "sed" ने एक गलत लाइन हटा दी। इसलिए मैं इस दृष्टिकोण का उपयोग: sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'। धन्यवाद!
एडुआर्डो लुसियो

यहाँ भी, मैंने एक लूप लिखा और अजीब तरह से कुछ फाइलें सही लाइन खो गई लेकिन कुछ फाइलें एक-दूसरे को भी खो गईं, कोई सुराग नहीं है कि क्या गलत हुआ। (GNU / Linux bash4.2) नीचे awk कमांड लूप में ठीक काम करता है
FatihSarigol

यदि आप लाइनों की एक सूची से हटा रहे हैं, तो क्रमबद्ध -r का उपयोग करने के लिए वास्तव में सावधान रहें, अन्यथा आपकी पहली सीड हर चीज की रेखा को बदल देगी! ...
कोंचोग

एक लूप के भीतर गलत लाइनों को हटाने के बारे में टिप्पणी करने के लिए: सबसे बड़ी लाइन नंबर के साथ शुरू करना सुनिश्चित करें, अन्यथा प्रत्येक हटाए गए लाइन लाइन नंबरिंग को ऑफसेट करेगा ...
Skippy le Grand Gourou

25

और साथ ही जाग

awk 'NR!~/^(5|10|25)$/' file

2
नायब: उस ओके लाइन ने मेरे लिए सेड वैरिएंट (ओएस-एक्स और उबंटू लिनक्स के बीच) की तुलना में अधिक भरोसेमंद रूप से काम किया
जे टेलर टेलर

3
ध्यान दें कि यह फ़ाइल में कुछ भी नहीं हटाता है। यह सिर्फ इन पंक्तियों के बिना फ़ाइल को प्रिंट करने के लिए प्रिंट करता है। इसलिए आपको आउटपुट को एक अस्थायी फ़ाइल पर पुनर्निर्देशित करने की भी आवश्यकता है, और फिर मूल को बदलने के लिए अस्थायी फ़ाइल को स्थानांतरित करें।
9


6

यह अक्सर एक एंटीपेटर्न का लक्षण होता है। जिस टूल ने लाइन नंबरों का निर्माण किया है, उसे अच्छी तरह से बदल दिया जा सकता है, जो लाइनों को तुरंत हटा देता है। उदाहरण के लिए;

grep -nh error logfile | cut -d: -f1 | deletelines logfile

(जहां deletelinesआप जिस उपयोगिता की कल्पना कर रहे हैं, उसकी जरूरत है) वैसी ही है

grep -v error logfile

यह कहते हुए कि, यदि आप ऐसी स्थिति में हैं, जहाँ आपको वास्तव में इस कार्य को करने की आवश्यकता है, तो आप sedलाइन नंबरों की फाइल से एक सरल स्क्रिप्ट तैयार कर सकते हैं । विनोदी (लेकिन शायद थोड़ा भ्रमित) आप इसके साथ कर सकते हैं sed

sed 's%$%d%' linenumbers

यह लाइन नंबरों की एक फाइल को स्वीकार करता है, एक प्रति पंक्ति, और मानक आउटपुट पर, dप्रत्येक के बाद एपेंडेड के साथ एक ही लाइन नंबर का उत्पादन करता है । यह एक मान्य sedस्क्रिप्ट है, जिसे हम किसी फ़ाइल, या (कुछ प्लेटफार्मों पर) पाइप से दूसरे sedउदाहरण में सहेज सकते हैं :

sed 's%$%d%' linenumbers | sed -f - logfile

कुछ प्लेटफार्मों पर, sed -fविकल्प तर्क समझ में नहीं करता है -मतलब मानक इनपुट करने के लिए है, तो आप एक अस्थायी फ़ाइल के लिए स्क्रिप्ट अनुप्रेषित करने के लिए है, और यह साफ है जब आप पूरा कर लें, या हो सकता है के साथ अकेला डैश की जगह /dev/stdinया /proc/$pid/fd/1अपने OS (या खोल अगर ) के पास है।

हमेशा की तरह, आप मानक आउटपुट पर परिणाम का उत्पादन करने के बजाय, लक्ष्य फ़ाइल को संपादित करने -iके -fविकल्प से पहले जोड़ सकते हैं sed। * BSDish प्लेटफार्मों (OSX सहित) पर आपको एक स्पष्ट तर्क की आपूर्ति करने की आवश्यकता है -i; एक सामान्य मुहावरा एक खाली तर्क की आपूर्ति करना है; -i ''


मैं "एक एंटीपार्टन के लक्षण" से बिल्कुल सहमत नहीं हूं। मार्कअप-आधारित फ़ाइल प्रकार (जैसे XML या JSON) को मान्य फ़ाइलों के क्रम में अंत में विशिष्ट लाइनों की आवश्यकता होती है। उस स्थिति में, यह अक्सर उन लाइनों को हटाने के लिए सबसे उचित दृष्टिकोण होता है, उस फ़ाइल में डाल दिया जाता है जिसे आप जोड़ा जाना चाहते हैं और फिर उन पंक्तियों को फिर से जोड़ते हैं, क्योंकि सीधी रेखाओं के बीच में डालने से बहुत अधिक प्रयास हो सकता है, और इसके खिलाफ जाता है जितना संभव हो उतना अतिरिक्त साधनों से बचने की संभावित इच्छा।
ईगोर हंस

मैं बिल्कुल नहीं समझता कि आप किस प्रकार के परिदृश्य की कल्पना कर रहे हैं। वहाँ रहे हैं स्थितियों में, जहां इस एक वैध दृष्टिकोण लेकिन मामलों मैंने देखा है की विशाल बहुमत है newbies जो कम या ज्यादा क्या मेरी पहली उदाहरण दर्शाता कर रहे हैं। (शायद वे कुछ वास्तव में निम्न-स्तरीय भाषा से आते हैं और उनकी समस्या को आणविक स्तर से अलग करने के लिए उपयोग किया जाता है, क्योंकि आपको asm या C. में होना है)
tripleee

एक्सएमएल या जेएसएन से लाइन नंबर द्वारा सामान निकालना , बिल्कुल खतरनाक नहीं है।
ट्रिपल

मूल रूप से मेरा क्या मतलब है, यह है कि ऐसी फाइल के निर्माता के रूप में, आपको पता है कि दस्तावेज़ के अंत में क्या होना चाहिए (यानी JSON के लिए अंतिम कुछ पंक्तियों में समापन ब्रेसिज़ / वर्ग कोष्ठक का सेट, या सटीक XML के लिए टैग बंद करना)। उस के बारे में पता होने के नाते, इस तरह के एक दस्तावेज़ का विस्तार करने के लिए सबसे सरल दृष्टिकोण 1 है) पिछली कुछ पंक्तियों को हटा दें, 2) नई सामग्री जोड़ें, 3) अंतिम कुछ पंक्तियों को फिर से जोड़ें। इस तरह, दस्तावेज़ को पहले और बाद में दोनों के लिए वैध किया जा सकता है, लाइनों को मध्य-दस्तावेज़ जोड़ने का एक तरीका खोजने की आवश्यकता के बिना।
ईगोर हंस

1
अब तक यह एक बड़ी संख्या के लिए उपयुक्त समाधान के साथ एकमात्र उत्तर है (यानी एक फ़ाइल द्वारा प्रदान किया गया है)। और अग्रदूत भी समझ में आता है। यह अधिक उत्थान के योग्य है। Btw, यदि आप चाहते हैं मुद्रित लाइनों के बजाय हटाने के लिए उन्हें, का उपयोग pकरने के बजाय d, विकल्प के साथ -n(यह बिना काम नहीं करेगा -n, और !dया तो काम नहीं करेगा)।
स्किप्पी ले ग्रैंड गौरू

2

मैं जाग के साथ एक सामान्यीकरण का प्रस्ताव करना चाहूंगा।

जब फ़ाइल एक निश्चित आकार के ब्लॉक द्वारा बनाई जाती है और हटाने के लिए लाइनें प्रत्येक ब्लॉक के लिए दोहराई जाती हैं, तो इस तरह से काम करना ठीक हो सकता है

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  $0}'
 OriginFile.dat > MyOutputCuttedFile.dat

इस उदाहरण में ब्लॉक के लिए आकार 2000 है और मैं लाइनों को प्रिंट करना चाहता हूं [1..713] और [1026..1029]।

  • NR वर्तमान लाइन संख्या को संग्रहीत करने के लिए awk द्वारा उपयोग किया जाने वाला चर है।
  • % दो पूर्णांकों के विभाजन का शेष (या मापांक) देता है;
  • nl=((NR-1)%BLOCKSIZE)+1यहां हम वेरिएबल nl में वर्तमान ब्लॉक के अंदर लाइन नंबर लिखते हैं । (निचे देखो)
  • ||और &&तार्किक ऑपरेटर हैं OR और AND हैं
  • print $0 पूरी लाइन लिखता है

Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
  +1   We add again 1 because we want to restore the desired order.

+-----+------+----------+------------+
| NR  | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
|  1  |  1   |    0     |     1      |
|  2  |  2   |    1     |     2      |
|  3  |  0   |    2     |     3      |
|  4  |  1   |    0     |     1      |
+-----+------+----------+------------+


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