`टेल` और` हेड` के लिए उलटा व्यवहार कैसे प्राप्त करें?


55

क्या कोई दस्तावेज़ head/ tailरिवर्स आउटपुट प्राप्त करने का एक तरीका है ; क्योंकि आप नहीं जानते कि किसी दस्तावेज़ में कितनी लाइनें हैं?

यानी मैं केवल सब कुछ प्राप्त करना चाहता हूं, लेकिन foo.txtदूसरे दस्तावेज़ में संलग्न होने की पहली 2 लाइनें ।

जवाबों:


57

आप इसका उपयोग पहली दो पंक्तियों को हटाने के लिए कर सकते हैं :

tail -n +3 foo.txt

और यह अंतिम दो पंक्तियों को स्ट्रिप करने के लिए :

head -n -2 foo.txt

(यह मानते हुए कि फ़ाइल \nबाद के लिए समाप्त होती है )


बस के मानक उपयोग के लिए tailऔर headइन आपरेशनों विनाशकारी नहीं हैं। >out.txtयदि आप आउटपुट को कुछ नई फ़ाइल पर पुनर्निर्देशित करना चाहते हैं तो उपयोग करें :

tail -n +3 foo.txt >out.txt

out.txtपहले से मौजूद मामले में , यह इस फाइल को अधिलेखित कर देगा। का प्रयोग करें >>out.txtबजाय >out.txtआप बल्कि उत्पादन के साथ जोड़ दिया है चाहते हैं तो out.txt


3
फिर से "सिर, जब फ़ाइल के साथ समाप्त होता \n" .. यह सब नकारात्मक पूर्णांक के अलावा अन्य के लिए काम करता है -n -0जो देता है कुछ भी नहीं , बस के रूप में -n 0होता है (का उपयोग करते हुए: सिर (GNU coreutils) 7.4) ... लेकिन जब पीछे \nमौजूद है, -n -0प्रिंट करता है जैसा कि उम्मीद की जा सकती है -, अर्थात। यह पूरी फ़ाइल को प्रिंट करता है ... इसलिए यह सभी गैर-शून्य नकारात्मक मानों के लिए काम करता है .. लेकिन -0जब कोई अनुगामी नहीं होता है\n
पीटर।

@ पसंदीदा: वास्तव में अजीब ... (8.12 के साथ यहां)।
स्टीफन जिमेनेज़

क्या यह ऑपरेशन विनाशकारी है? जैसा कि मैं चाहता हूं कि यह दस्तावेज़ की पहली दो पंक्तियों के व्युत्क्रम को दूसरे में कॉपी करे?
क्रिसजली

@ क्रिस: नहीं, वे सिर्फ अपने "मानक आउटपुट" पर परिणाम प्रिंट करते हैं, जो आमतौर पर टर्मिनल से जुड़ा होता है। मैंने कुछ फ़ाइलों में आउटपुट रीडायरेक्ट करने के तरीके के बारे में कुछ विवरण जोड़े हैं।
स्टीफन जिमेनेज़

7
head -n -2POSIX संगत नहीं है ।
l0b0

9

यदि आप सभी लेकिन पहली एन -1 लाइनों चाहते हैं, तो लाइनों tailकी संख्या के साथ कॉल करें +N। (संख्या वह पहली पंक्ति है जिसे आप बनाए रखना चाहते हैं, 1 से शुरू होकर, +1 का मतलब शीर्ष पर शुरू होता है, +2 का अर्थ है एक पंक्ति और इसी तरह छोड़ें)।

tail -n +3 foo.txt >>other-document

अंतिम N लाइनों को छोड़ने का कोई आसान, पोर्टेबल तरीका नहीं है। GNU एक समकक्ष के रूप में headअनुमति देता head -n +Nहै tail -n +N। अन्यथा, यदि आपके पास tac(जैसे कि जीएनयू या बिजीबॉक्स) है, तो आप इसे पूंछ के साथ जोड़ सकते हैं:

tac | tail -n +3 | tac

आंशिक रूप से, आप एक awk फ़िल्टर का उपयोग कर सकते हैं (अप्रयुक्त):

awk -vskip=2 '{
    lines[NR] = $0;
    if (NR > skip) print lines[NR-skip];
    delete lines[NR-skip];
}'

यदि आप किसी बड़ी फ़ाइल से अंतिम कुछ पंक्तियों को निकालना चाहते हैं, तो आप टुकड़े टुकड़े करने के लिए बाइट ऑफ़सेट का निर्धारण कर सकते हैं और फिर ट्रंकेशन को निष्पादित कर सकते हैं dd

total=$(wc -c < /file/to/truncate)
chop=$(tail -n 42 /file/to/truncate | wc -c)
dd if=/dev/null of=/file/to/truncate seek=1 bs="$((total-chop))"

आप शुरुआत में किसी फ़ाइल को काट नहीं सकते, हालाँकि यदि आपको किसी बड़ी फ़ाइल की पहली कुछ पंक्तियाँ निकालने की आवश्यकता है, तो आप सामग्री को इधर-उधर कर सकते हैं


कुछ सिस्टम (आधुनिक लिनक्स की तरह), आप शुरुआत में एक फ़ाइल को अलग कर सकते हैं (संक्षिप्त कर सकते हैं), लेकिन आमतौर पर केवल उस राशि से होता है जो एफएस ब्लॉक आकार से अधिक है (इसलिए इस मामले में वास्तव में उपयोगी नहीं है)।
स्टीफन चेज़लस

3

से tailआदमी पेज (जीएनयू tail, कि है):

-n, --lines=K
   output the last K lines, instead of the last 10; or use -n +K to
   output lines starting with the Kth

इस प्रकार, निम्नलिखित सभी लेकिन पहले 2 लाइनों के somefile.txtलिए संलग्न करना चाहिए anotherfile.txt:

tail --lines=+3 somefile.txt >> anotherfile.txt

3

पहली n लाइनों को हटाने के लिए GNU sed का उपयोग किया जा सकता है। उदाहरण के लिए यदि n = 2

sed -n '1,2!p' input-file

!मतलब है "इस अंतराल को बाहर"। जैसा कि आप कल्पना कर सकते हैं, अधिक जटिल परिणाम प्राप्त किया जा सकता है, उदाहरण के लिए

sed -n '3,5p;7p'

यह लाइन 3,4,5,7 दिखाएगा। अधिक शक्ति पतों के बजाय नियमित अभिव्यक्तियों के उपयोग से आती है।

सीमा यह है कि लाइनों की संख्या पहले से ज्ञात होनी चाहिए।


1
सिर्फ क्यों नहीं sed 1,2d? सरलता आमतौर पर बेहतर होती है। इसके अलावा, आपके उदाहरणों में कुछ भी GNU Sed के लिए विशिष्ट नहीं है; आपके आदेश सेड के सभी मानक POSIX सुविधाओं का उपयोग करते हैं ।
वाइल्डकार्ड

1

आप मूल फ़ाइल diffके आउटपुट head/ की तुलना करने के लिए उपयोग कर सकते हैं tailऔर फिर वही हटा सकते हैं, जिससे उलटा हो रहा है।

diff --unchanged-group-format='' foo.txt <(head -2 foo.txt)

1

जबकि tail -n +4उत्पादन के लिए फ़ाइल 4 लाइन पर शुरू (सभी लेकिन पहले 3 लाइनों) मानक और पोर्टेबल है, इसके headसमकक्ष ( head -n -3, सभी लेकिन पिछले 3 लाइनों) नहीं है।

आंशिक रूप से, आप करेंगे:

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

या:

sed -ne :1 -e '1,3{N;b1' -e '}' -e 'P;N;D'

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

या:

awk 'NR>3 {print l[NR%3]}; {l[NR%3]=$0}'

1
{   head -n2 >/dev/null
    cat  >> other_document
}   <infile

यदि <infileएक नियमित, lseek()-योग्य फ़ाइल है, तो हाँ, हर तरह से, स्वतंत्र महसूस करें। उपरोक्त पूरी तरह से POSIXly समर्थित निर्माण है।


0

मेरा दृष्टिकोण गिल्स के समान है, लेकिन मैं इसके बजाय बिल्ली और पाइप के साथ फाइल को उल्टा करता हूं जो कि हेड कमांड के साथ है।

tac -r thefile.txt | हेड thisfile.txt (फ़ाइलों की जगह)


0

आशा है कि मुझे आपकी आवश्यकता स्पष्ट रूप से समझ में आ गई।

अपना अनुरोध पूरा करने के लिए आपके पास कई तरीके हैं:

tail -n$(expr $(cat /etc/passwd|wc -l) - 2) /etc/passwd

जहाँ / etc / passwd आपकी फ़ाइल है

यदि आपके पास बहुत बड़ी फ़ाइल है तो दूसरा समाधान उपयोगी हो सकता है:

my1stline=$(head -n1 /etc/passwd)
my2ndline=$(head -n2 /etc/passwd|grep -v "$my1stline")
cat /etc/passwd |grep -Ev "$my1stline|$my2ndline"

0

बीएसडी के लिए समाधान (macOS):

पहले 2 लाइनें निकालें:

tail -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

अंतिम 2 लाइनें निकालें:

head -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

... बहुत सुंदर नहीं है, लेकिन काम हो जाता है!

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