कहो कि आपके पास एक txt फ़ाइल है, शीर्ष 10 लाइनों और फ़ाइल के निचले 10 लाइनों को एक साथ देखने के लिए क्या कमांड है?
यानी यदि फाइल 200 लाइनों की है, तो लाइनों को 1-10 और 190-200 में एक बार में देखें।
कहो कि आपके पास एक txt फ़ाइल है, शीर्ष 10 लाइनों और फ़ाइल के निचले 10 लाइनों को एक साथ देखने के लिए क्या कमांड है?
यानी यदि फाइल 200 लाइनों की है, तो लाइनों को 1-10 और 190-200 में एक बार में देखें।
जवाबों:
आप बस:
(head; tail) < file.txt
और अगर आपको किसी कारणवश पाइप का उपयोग करने की आवश्यकता है, तो इस तरह से करें:
cat file.txt | (head; tail)
नोट: डुप्लिकेट की गई लाइनों को प्रिंट करेगा यदि फ़ाइल में लाइनों की संख्या। txt सिर की डिफ़ॉल्ट लाइनों की तुलना में छोटी है + पूंछ की डिफ़ॉल्ट लाइनें।
head
ने फ़ाइल की पहली 10 पंक्तियों को खा लिया है। ( head < file.txt; tail < file.txt
20 से कम लाइनों वाली फ़ाइल पर इसकी तुलना करें )। बस एक बहुत ही मामूली बात ध्यान में रखना है। (लेकिन फिर भी +1।)
head
केवल इसके इनपुट की पहली 10 पंक्तियों को प्रदर्शित करता है, इस बात की कोई गारंटी नहीं है कि यह 10 वीं पंक्ति को समाप्त करने के लिए इसका अधिक उपभोग नहीं करता है , less
प्रदर्शन के लिए इनपुट के कम छोड़ देता है।
seq 100 | (head; tail)
मुझे केवल पहले 10 नंबर देता है। केवल बहुत बड़े इनपुट आकार पर (जैसे seq 2000
) पूंछ को कुछ इनपुट मिलता है।
एक शुद्ध धारा (उदाहरण के लिए एक कमांड से आउटपुट) के लिए, आप 'टी' का उपयोग स्ट्रीम को कांटा करने के लिए कर सकते हैं और एक स्ट्रीम को हेड और एक को टेल पर भेज सकते हैं। इसके लिए या तो '> (सूची)' सुविधा का उपयोग करना आवश्यक है (+ / dev / fd / N):
( COMMAND | tee /dev/fd/3 | head ) 3> >( tail )
या जटिल पुनर्निर्देशन के साथ / dev / fd / N (या / dev / stderr) प्लस उप-भाग का उपयोग करना:
( ( seq 1 100 | tee /dev/fd/2 | head 1>&3 ) 2>&1 | tail ) 3>&1
( ( seq 1 100 | tee /dev/stderr | head 1>&3 ) 2>&1 | tail ) 3>&1
(इनमें से कोई भी csh या tsh में काम नहीं करेगा।)
थोड़ा बेहतर नियंत्रण के साथ कुछ के लिए, आप इस पर्ल कमांड का उपयोग कर सकते हैं:
COMMAND | perl -e 'my $size = 10; my @buf = (); while (<>) { print if $. <= $size; push(@buf, $_); if ( @buf > $size ) { shift(@buf); } } print "------\n"; print @buf;'
COMMAND | { tee >(head >&2) | tail; } |& other_commands
cat >/dev/null
इसे ठीक करता है:COMMAND | { tee >(head >&2; cat >/dev/null) | tail; } |& other_commands
head
और tail
आदेशों के बीच कोई गारंटी नहीं है : \ ...
head -10 file.txt; tail -10 file.txt
इसके अलावा, आपको अपना कार्यक्रम / स्क्रिप्ट लिखने की आवश्यकता होगी।
cat
और head
या tail
पाइप किया है, यह जानने के लिए अच्छा है कि मैं उन्हें व्यक्तिगत रूप से उपयोग कर सकता हूं!
{ head file; tail file; } | prog
जेएफ सेबेस्टियन की टिप्पणी पर आधारित :
cat file | { tee >(head >&3; cat >/dev/null) | tail; } 3>&1
इस तरह आप पहली पंक्ति और शेष को अलग-अलग एक पाइप में संसाधित कर सकते हैं, जो सीएसवी डेटा के साथ काम करने के लिए उपयोगी है:
{ echo N; seq 3;} | { tee >(head -n1 | sed 's/$/*2/' >&3; cat >/dev/null) | tail -n+2 | awk '{print $1*2}'; } 3>&1
एन * 2 2 4 6
यहाँ समस्या यह है कि स्ट्रीम-ओरिएंटेड प्रोग्राम फाइल की लंबाई पहले से नहीं जानते हैं (क्योंकि हो सकता है कि यह एक वास्तविक स्ट्रीम न हो)।
उपकरण की तरह tail
पिछले n लाइनों देखा बफ़र और धारा के अंत के लिए प्रतीक्षा करें, फिर प्रिंट करें।
यदि आप इसे एक ही आदेश में करना चाहते हैं (और यह किसी भी ऑफसेट के साथ काम करता है, और लाइनों को दोहराना नहीं है अगर वे ओवरलैप करते हैं) तो आपको मेरे द्वारा बताए गए इस व्यवहार का अनुकरण करना होगा।
इस अजीब कोशिश:
awk -v offset=10 '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' yourfile
a.out | awk -v ...
इस समाधान को समाप्त करने में बहुत समय लगा, जो ऐसा प्रतीत होता है कि सभी उपयोग मामलों को कवर किया गया है (अब तक):
command | tee full.log | stdbuf -i0 -o0 -e0 awk -v offset=${MAX_LINES:-200} \
'{
if (NR <= offset) print;
else {
a[NR] = $0;
delete a[NR-offset];
printf "." > "/dev/stderr"
}
}
END {
print "" > "/dev/stderr";
for(i=NR-offset+1 > offset ? NR-offset+1: offset+1 ;i<=NR;i++)
{ print a[i]}
}'
सुविधा की सूची:
मैं कुछ समय के लिए इस समाधान के लिए देख रहा हूँ। इसे स्वयं सेड के साथ करने की कोशिश की, लेकिन पहले से फ़ाइल / स्ट्रीम की लंबाई न जानने की समस्या लाज़मी थी। उपरोक्त सभी विकल्पों में से, मुझे केमिली गौडेय्यून के जाग समाधान पसंद हैं। उन्होंने यह नोट किया कि उनके समाधान ने पर्याप्त रूप से छोटे डेटा सेट के साथ आउटपुट में अतिरिक्त रिक्त लाइनें छोड़ दीं। यहां मैं उनके समाधान का एक संशोधन प्रदान करता हूं जो अतिरिक्त लाइनों को हटा देता है।
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { a_count=0; for (i in a) {a_count++}; for (i=NR-a_count+1; i<=NR; i++) print a[i] }' ; }
खैर, आप हमेशा उन्हें एक साथ चेन कर सकते हैं। , इसलिए चाहते
head fiename_foo && tail filename_foo
। यदि यह पर्याप्त नहीं है, तो आप अपनी .profile फ़ाइल या आपके द्वारा उपयोग की जाने वाली किसी भी लॉगिन फ़ाइल में अपने आप को एक bash फ़ंक्शन लिख सकते हैं:
head_and_tail() {
head $1 && tail $1
}
और, बाद में इसे अपने शेल प्रॉम्प्ट से मंगवाएं head_and_tail filename_foo
:।
पहले 10 लाइनें file.ext, फिर इसकी आखिरी 10 लाइनें:
cat file.ext | head -10 && cat file.ext | tail -10
फ़ाइल की अंतिम 10 लाइनें, फिर पहले 10:
cat file.ext | tail -10 && cat file.ext | head -10
फिर आप आउटपुट को कहीं और भी पाइप कर सकते हैं:
(cat file.ext | head -10 && cat file.ext | tail -10 ) | your_program
tail
और head
या एक फ़ंक्शन में भेजती है ।
मैंने ऐसा करने के लिए एक साधारण अजगर ऐप लिखा: https://gist.github.com/garyvdm/9970522
यह पाइप (धाराओं) के साथ-साथ फाइलों को भी संभालता है।
फ़ाइलों के साथ-साथ पाइप (स्ट्रीम) को संभालने के लिए, इसे अपनी .bashrc या .profile फ़ाइल में जोड़ें।
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' ; }
तब आप ही नहीं कर सकते
headtail 10 < file.txt
लेकिन
a.out | headtail 10
(यह अभी भी स्पष्ट रिक्त लाइनों को लागू करता है जब 10 इनपुट की लंबाई से अधिक होता है, सादे पुराने के विपरीत a.out | (head; tail)
। धन्यवाद, पिछले उत्तरदाताओं।)
नोट: headtail 10
नहीं headtail -10
।
@Aleksandra Zalcman की कमांड कैसे काम करती है, इस बारे में @Samus_ ने यहां बताया कि यह भिन्नता तब आसान है जब आप जल्दी से उस स्थान पर नहीं पहुंच सकते जहां पूंछ बिना लाइनों की गिनती के शुरू होती है।
{ head; echo "####################\n...\n####################"; tail; } < file.txt
या यदि आप 20 लाइनों के अलावा किसी अन्य चीज से काम करना शुरू करते हैं, तो एक पंक्ति गणना भी मदद कर सकती है।
{ head -n 18; tail -n 14; } < file.txt | cat -n
किसी फ़ाइल की पहली 10 और अंतिम 10 पंक्तियों को प्रिंट करने के लिए, आप यह कोशिश कर सकते हैं:
cat <(head -n10 file.txt) <(tail -n10 file.txt) | less
sed -n "1,10p; $(( $(wc -l ${aFile} | grep -oE "^[[:digit:]]+")-9 )),\$p" "${aFile}"
नोट : aFile वैरिएबल में फ़ाइल का पूर्ण पथ है ।
मैं कहूंगा कि फ़ाइल के आकार के आधार पर, इसकी सामग्रियों में सक्रिय रूप से पढ़ना वांछनीय नहीं हो सकता है। उस परिस्थिति में, मुझे लगता है कि कुछ सरल शेल स्क्रिप्टिंग को पर्याप्त होना चाहिए।
यहां बताया गया है कि हाल ही में मैंने कितनी बड़ी CSV फ़ाइलों का विश्लेषण किया था, जिनका मैं विश्लेषण कर रहा था:
$ for file in *.csv; do echo "### ${file}" && head ${file} && echo ... && tail ${file} && echo; done
यह प्रत्येक फ़ाइल के पहले 10 लाइनों और अंतिम 10 लाइनों को प्रिंट करता है, जबकि फ़ाइल नाम और कुछ दीर्घवृत्त को प्रिंट करने से पहले और बाद में भी।
एक बड़ी फ़ाइल के लिए, आप बस उसी प्रभाव के लिए निम्नलिखित चला सकते हैं:
$ head somefile.csv && echo ... && tail somefile.csv
स्टड का उपभोग करता है, लेकिन सरल और उपयोग के मामलों के 99% के लिए काम करता है
#!/usr/bin/env bash
COUNT=${1:-10}
IT=$(cat /dev/stdin)
echo "$IT" | head -n$COUNT
echo "..."
echo "$IT" | tail -n$COUNT
$ seq 100 | head_and_tail 4
1
2
3
4
...
97
98
99
100