किसी फ़ाइल की अंतिम n लाइनों को हटाने के लिए sed का उपयोग कैसे करें


148

मैं एक फ़ाइल के अंत से कुछ एन लाइनें निकालना चाहता हूं । क्या यह sed का उपयोग करके किया जा सकता है?

उदाहरण के लिए, 2 से 4 तक लाइनों को हटाने के लिए, मैं उपयोग कर सकता हूं

$ sed '2,4d' file

लेकिन मैं लाइन नंबर नहीं जानता। मैं अंतिम लाइन का उपयोग करके हटा सकता हूं

$sed $d file

लेकिन मैं अंत से n लाइनों को हटाने का तरीका जानना चाहता हूं । कृपया मुझे पता है कि कैसे sed या किसी अन्य विधि का उपयोग करने के लिए।


2
@arashkordi: जो फ़ाइल के शीर्ष से एक पंक्ति-गिनती का उपयोग करता है, नीचे नहीं।
एम्स

सुपरसर्स पर संबंधित प्रश्न ।
Thor

//, शायद सवाल की तुलना में यह अधिक सामान्य बनाना अलग ढंग से व्यक्त करने पर विचार बस sed ?
नाथन बासानी

1
sed $d fileकोई त्रुटि देता है। इसके बजाय, $ d को उद्धरणों के भीतर होना चाहिए, जैसे:sed '$d' file
Akronix

जवाबों:


221

मैं इसके बारे में नहीं जानता sed, लेकिन इसके साथ किया जा सकता है head:

head -n -2 myfile.txt

19
सादगी के लिए +1। समतुल्य सीड कमांड बट बदसूरत है: sed -e :a -e '$d;N;2,5ba' -e 'P;D' file( ,5पिछले 5 लाइनों के लिए)।
मार्क बी

62
ध्यान दें कि यह कुछ संस्करणों के साथ काम करता है head, लेकिन मानक नहीं है। वास्तव में, headराज्यों के लिए मानक :The application shall ensure that the number option-argument is a positive decimal integer.
विलियम पर्सेल

21
@ विलियमप्रसेल के जवाब में जोड़ने के लिए ... मैक ओएस डिफ़ॉल्ट शेल पर, यह काम नहीं करता है।
JDS

7
न ही बीएसडी पर, लेकिन सवाल लिनक्स को टैग किया गया है।
आम

3
माइनस 1, क्योंकि, ओएक्सएक्स के अलावा, यह मेरे लिए Ubuntu14 पर काम नहीं कर रहा है -head: illegal line count -- -2
माइकल

30

यदि हार्डकोडिंग एन एक विकल्प है, तो आप सीड करने के लिए अनुक्रमिक कॉल का उपयोग कर सकते हैं। उदाहरण के लिए, अंतिम तीन पंक्तियों को हटाने के लिए, पिछली एक पंक्ति को तीन बार हटाएं:

sed '$d' file | sed '$d' | sed '$d'

2
यह, प्लस -i फाइल को स्टडआउट करने के बजाय जगह में संपादित करने के लिए, मेरे लिए काम किया।
डब्ल्यूएएफ

27

से sed एक-लाइनर्स :

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

लगता है कि आप के लिए क्या कर रहे हैं।


@Thor आप को बदलने के द्वारा कितने लाइनों फ़ाइल से निकाल दिए जाते हैं बदल सकते हैं 10में'$d;N;2,10ba'
Alexej मगुरा

1
@AlexejMagura: मैं उत्तर के पुराने संस्करण पर टिप्पणी कर रहा था।
थोर

22

एक मज़ेदार और सरल sedऔर tacसमाधान:

n=4
tac file.txt | sed "1,$n{d}" | tac

ध्यान दें

  • "शेल के लिए कमांड $nमें चर का मूल्यांकन करने के लिए दोहरे उद्धरण चिह्नों की आवश्यकता होती है sed। एकल उद्धरणों में, कोई भी प्रक्षेप नहीं किया जाएगा।
  • tacएक catउलट है, देखेंman 1 tac
  • {}में sedवहाँ अलग करने के लिए कर रहे हैं $nऔर d(यदि नहीं, लगाना गैर विद्यमान को खोल कोशिश $ndचर)

7
tacosx पर fyi no
माइकल डुरंट

1
@MichaelDurrant port info coreutils|| brew info coreutils;
आवाज

19

उपयोग करें sed, लेकिन शेल को गणित करने दें, लक्ष्य dको एक सीमा देकर कमांड का उपयोग करने के लिए (अंतिम 23 लाइनों को हटाने के लिए):

sed -i "$(($(wc -l < file)-22)),\$d" file

पिछली 3 लाइनों को हटाने के लिए, अंदर से बाहर:

$(wc -l < file)

फ़ाइल की लाइनों की संख्या देता है: 2196 कहते हैं

हम पिछली 23 लाइनों को हटाना चाहते हैं, इसलिए बाईं ओर या सीमा के लिए:

$((2196-22))

देता है: 2174 इस प्रकार शैल व्याख्या के बाद मूल सेड है:

sed -i '2174,$d' file

-iInplace एडिट करने के साथ , फाइल अब 2173 लाइनें है!

यदि आप इसे एक नई फ़ाइल में सहेजना चाहते हैं, तो कोड है:

sed -i '2174,$d' file > outputfile

15

आप इसके लिए सिर का उपयोग कर सकते हैं ।

उपयोग

$ head --lines=-N file > new_file

जहाँ N वह संख्या है जिसे आप फ़ाइल से निकालना चाहते हैं।

मूल फ़ाइल की पिछली N लाइन की सामग्री अब new_file में है


8

पूर्णता के लिए मैं अपना समाधान जोड़ना चाहूंगा। मैंने इसे मानक के साथ पूरा किया ed:

ed -s sometextfile <<< $'-2,$d\nwq'

यह इन-प्लेस संपादन का उपयोग करके अंतिम 2 पंक्तियों को हटा देता है (हालांकि यह एक अस्थायी फ़ाइल का उपयोग करता है /tmp!!)


5

वास्तव में हमारे पास truncateकमांड में बहुत बड़ी फ़ाइलों को ट्रंकुकेट करने के लिए । यह लाइनों के बारे में नहीं जानता, लेकिन tail+ wcलाइनों को बाइट्स में बदल सकता है:

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

यदि एक ही समय में फ़ाइल लिखी जाती है, तो एक स्पष्ट दौड़ की स्थिति होती है। इस मामले में इसका उपयोग करना बेहतर हो सकता है head- यह फ़ाइल (माइंड डिस्क आईओ) की शुरुआत से बाइट्स को गिनता है, इसलिए हम हमेशा लाइन सीमा पर ट्रंकटेट करेंगे (संभवतः फ़ाइल सक्रिय रूप से लिखे जाने पर अपेक्षा से अधिक लाइनें):

truncate -s $(head -n -$lines $file | wc -c) $file

यदि आप उपयोगकर्ता नाम के स्थान पर पासवर्ड डालने का असफल प्रयास विफल करते हैं, तो एक-लाइनर:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

4

यह आपके लिए काम कर सकता है (GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file

अच्छा लगा। आप समाप्त होने वाले एपोस्ट्रोफ ( ') से चूक गए ।
Thor

इतनी देर की टिप्पणी के लिए खेद है, लेकिन मैं कोशिश करता हूं और (मेरे एआईएक्स / पॉज़िक्स के लिए आदरणीय) यह सभी लेकिन अंतिम पंक्ति छपाई में विफल रहा। कोड को पढ़ना, मुझे समझ में नहीं आता है कि अंतिम चार लाइनें कैसे हटा दी जाती हैं, स्पष्ट लूप 4 पहली लाइनों पर है, इसलिए यह निश्चित रूप से लूप के बाद d, Dया Pजीएनयू सेड के साथ और पॉज़िक्स संस्करण पर नहीं। Dएक्शन लाइन के 'अंत' को पास किए बिना नए लूप के लिए बफर काम करने के बाद लगता है और काम नहीं कर रहा है।
NeronLeVelu

@NeronLeVelu प्रोग्राम 4 लाइनों की विंडो में पैटर्न स्पेस में पढ़ता है और फिर अगली लाइन को जोड़ देता है और पहले तक प्रिंट करता है जब तक कि यह फ़ाइल के अंत तक नहीं पहुंच जाता है जहां यह शेष लाइनों को हटा देता है।
पोटोंग

@potong हाँ, मैं एक GNU sed पर परीक्षण करता हूँ और यह उन लाइनों के बीच बफर को रखता है जहाँ पॉज़िक्स इसे Dविपरीत प्रभाव बनाने के बाद उतार देता है।
NeronLeVelu

4

उपरोक्त उत्तरों में से अधिकांश में GNU कमांड / एक्सटेंशन की आवश्यकता होती है:

    $ head -n -2 myfile.txt
    -2: Badly formed number

थोड़ा और अधिक सुगम्य समाधान के लिए:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

या

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

या

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

जहाँ "10" "n" है।


2

यहां दिए गए जवाबों से आपको पहले ही पता चल जाएगा कि इस एप्लिकेशन के लिए sed सबसे अच्छा टूल नहीं है।

हालाँकि मुझे लगता है कि सेड का उपयोग करने का एक तरीका है; विचार यह है कि एन लाइनों को जोड़ने के लिए अंतरिक्ष को पकड़ना है जिसे आप ईओएफ से टकराने के बिना पढ़ सकते हैं। जब ईओएफ मारा जाता है, तो होल्ड स्पेस की सामग्री को प्रिंट करें और छोड़ दें।

sed -e '$!{N;N;N;N;N;N;H;}' -e x

ऊपर दिया गया sed कमांड अंतिम 5 लाइनों को छोड़ देगा।


2

निम्नलिखित कमांड आज़माएं:

n = line number
tail -r file_name | sed '1,nd' | tail -r

कृपया बताएं कि यह कैसे काम करता है। FYI करें - शेल वेरिएबल्स को इनिशियलाइज़ करने के लिए, हमारे पास जगह नहीं होनी चाहिए =
कोडफ़ेस्टर

@codeforester पहली पंक्ति एक टिप्पणी थी जो मुझे लगता है। वह केवल उन स्थानों का उपयोग करता है tail -rजहां दूसरों ने tacलाइनों के क्रम को उल्टा करने के लिए उपयोग किया है, और अंतिम nपंक्तियों को nपहली पंक्ति बनाते हैं।
निकोलस मेले

2

इसे 3 चरणों में किया जा सकता है:

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

 n=`cat myfile |wc -l`

b) हटाने के लिए लाइनों की संख्या उस संख्या से घटाएं:

 x=$((n-3))

ग) उस पंक्ति संख्या ( $x) से अंत तक हटाने के लिए sed बताएं :

 sed "$x,\$d" myfile

बुरा गणित। यदि आपको 3 लाइनें हटानी हैं, तो 3 लेकिन ADD 1. घटाएं। आपके गणित के साथ, यदि फ़ाइल में 10 लाइनें, 10 - 3 = 7 हैं और आप sedलाइनों को 7 को 10 के माध्यम से हटाने के लिए उपयोग कर रहे हैं , तो यह 4 पंक्तियां हैं, न कि 3.
mathguy

1

आप लाइनों की कुल संख्या के साथ wc -l <file>और उपयोग प्राप्त कर सकते हैं

head -n <total lines - lines to remove> <file>


1

यह अंतिम 3 लाइनों को हटा देगा file:

for i in $(seq 1 3); do sed -i '$d' file; done;


1
यह बड़ी फ़ाइलों के लिए बहुत महंगा है - संपूर्ण फ़ाइल को n बार पढ़ा और फिर से लिखना होगा! और जितने कांटे हैं sed
codeforester

जबकि यह सबसे कुशल समाधान नहीं हो सकता है, यह सबसे सरल और समझने में आसान है
धर्म

0

मैं इस समाधान को पसंद करता हूं;

head -$(gcalctool -s $(cat file | wc -l)-N) file

जहां N को हटाने के लिए लाइनों की संख्या है।


0
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

पॉज़िक्स संस्करण


0

अंतिम 4 लाइनों को हटाने के लिए:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

थोड़ा भारी (विशेषकर संसाधनों में) एक सिर की तुलना में। कम से कम tac file | sed '1,4d' | tacक्योंकि सॉर्ट करें तो उपसर्ग लागत बहुत सारे स्रोतों को हटा दें।
NeronLeVelu

@NeronLeVelu आप सही हैं, लेकिन tacकुछ कमांड नहीं है (उदाहरण के लिए FreeBSD?)
mstafreshi

0

मैं इस के साथ आया था, जहाँ n वह संख्या है जिसे आप हटाना चाहते हैं:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

यह थोड़ा गोल चक्कर है, लेकिन मुझे लगता है कि इसका पालन करना आसान है।

  1. मुख्य फ़ाइल में लाइनों की संख्या की गणना करें
  2. उन पंक्तियों की संख्या को घटाएं जिन्हें आप गिनती से हटाना चाहते हैं
  3. टेम्पों फ़ाइल में उन पंक्तियों की संख्या प्रिंट करें, जिन्हें आप रखना चाहते हैं और संग्रहीत करना चाहते हैं
  4. मुख्य फ़ाइल को अस्थायी फ़ाइल से बदलें
  5. अस्थायी फ़ाइल निकालें

0

किसी फ़ाइल की अंतिम N लाइनों को हटाने के लिए, आप उसी अवधारणा का उपयोग कर सकते हैं

$ sed '2,4d' file

आप फ़ाइल को उलटने के लिए टेल कमांड के साथ कॉम्बो का उपयोग कर सकते हैं: यदि एन 5 है

$ tail -r file | sed '1,5d' file | tail -r > file

और यह रास्ता भी चलता है जहाँ head -n -5 fileकमांड नहीं चलता (जैसे मैक पर!)।


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