फ़ाइल के बीच में विशिष्ट लाइनें प्रदर्शित करने के लिए क्विक यूनिक्स कमांड?


206

एक सर्वर के साथ एक समस्या को डीबग करने की कोशिश कर रहा है और मेरी एकमात्र लॉग फ़ाइल 20GB लॉग फ़ाइल है (बिना टाइमस्टैम्प के भी! लोग System.out.println()लॉगिंग के रूप में क्यों उपयोग करते हैं ? उत्पादन में?)

Grep का उपयोग करते हुए, मुझे फ़ाइल का एक क्षेत्र मिला है, जिसे मैं 347340107 लाइन पर देखना चाहता हूँ।

कुछ ऐसा करने के अलावा

head -<$LINENUM + 10> filename | tail -20 

... जिसे headलॉग फ़ाइल की पहली 347 मिलियन लाइनों के माध्यम से पढ़ना होगा , क्या एक त्वरित और आसान कमांड है जो कंसोल पर 347340100 - 347340200 (उदाहरण के लिए) लाइनों को डंप करेगा?

अद्यतन मैं पूरी तरह से भूल गया कि grep एक मैच के आसपास के संदर्भ को मुद्रित कर सकता है ... यह अच्छी तरह से काम करता है। धन्यवाद!


मुझे लगता है कि grep को पूरी फाइल को खोजना होगा ऐसा करने के लिए एक सीपीयू कम गहन तरीका होना चाहिए।
ojblass

यह भी देखें stackoverflow.com/questions/6022384/...
flow2k

जवाबों:


69

GNU-grep के साथ आप बस कह सकते हैं

grep --context = 10 ...

7
या अधिक विशेष रूप से 10 लाइनों से पहले: grep -B 10 ... या 10 लाइनों के बाद: grep -A 10 ...
बॉय बॉकीमा

17
यह कमांड काम नहीं कर रहा है, नीचे sed -n '<start>, <end> p' काम कर रहा है
बसव

5
यह वास्तव में वह नहीं है जो आप चाहते हैं क्योंकि यह पूरी फ़ाइल को संसाधित करेगा भले ही मैच शीर्ष बिट में हो। इस बिंदु पर एक सिर / पूंछ या पूंछ / सिर कॉम्बो बहुत अधिक प्रभावी है।
स्किलिविज़

3
यह पूछे गए प्रश्न को बिल्कुल भी संतुष्ट नहीं करता है क्योंकि यह किसी विशिष्ट लाइन को आउटपुट करने का तरीका नहीं देता है , जैसा कि पूछा गया है।
क्रिस Rasys

1
यह वास्तव में नहीं है जो पूछा गया था। @matt b, आप इस उत्तर को क्यों नहीं स्वीकार करते?
user1271772

390

मैं दो अन्य समाधान पाया अगर आप लाइन नंबर जानते हैं, लेकिन और कुछ नहीं (संभव नहीं है):

यह मानते हुए कि आपको 20 से 40 लाइनों की आवश्यकता है,

sed -n '20,40p;41q' file_name

या

awk 'FNR>=20 && FNR<=40' file_name

6
+1: यद्यपि आप मुद्रण के बाद छोड़ना चाहते हैं। यदि फ़ाइल वास्तव में बहुत बड़ी है तो कुछ प्रदर्शन लाभ प्रदान कर सकते हैं।
जयपाल सिंह

awk 'NR> = 20 && NR <= 40' file_name
सुदीप्ता बसक

2
sed -n '20, 40p; 41q 'file_name फिर छोड़ने के लिए।
स्निग्धा बत्रा

1
विशेष रूप से, वे प्रारंभ और अंतिम पंक्ति संख्याएँ हैं। यदि आप एक बड़ी फ़ाइल में हैं तो यह '12345678,12345699p' होगा
कोड एबिनोमेटर

1
इसके अतिरिक्त @ CodeAbominator की टिप्पणी से 41qsed को लाइन छोड़ने का निर्देश दिया गया है 41
Brice

116
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3,  efficient on large files 

विधि 3 बड़ी फ़ाइलों पर कुशल

विशिष्ट लाइनों को प्रदर्शित करने का सबसे तेज़ तरीका


मैं यह जानने की कोशिश कर रहा हूं कि एकल पंक्ति के बजाय किसी श्रेणी का उपयोग करने के लिए पद्धति 3 को कैसे अनुकूलित किया जाए, लेकिन मुझे डर है कि मेरा sed-foo कार्य तक नहीं है।
Xiong Chiamiov

9
@XiongChiamiov 1-500 की छपाई के लिए sed -n '1,500p; 501q' के बारे में कैसे?
सैम

3
पहली दो पंक्तियों / विधियों के कम कुशल होने का कारण यह है कि वे पंक्ति 52 के बाद, अंत तक सभी पंक्तियों को संसाधित करना जारी रखते हैं, जबकि # 52 पंक्ति 52 की छपाई के बाद रुक जाती है।
flow2k

1
यह उत्तर यह समझाने से लाभान्वित होगा कि सभी तर्क क्या करते हैं।
ब्रैम वनरॉय

25

नहीं, फाइल लाइन-एड्रेसेबल नहीं है।

टेक्स्ट फ़ाइल में लाइन एन की शुरुआत खोजने का कोई निरंतर-समय तरीका नहीं है । आपको फ़ाइल के माध्यम से स्ट्रीम करना होगा और नए अंक गिनने होंगे।

सबसे सरल / सबसे तेज़ टूल का उपयोग करें जिसे आपको काम करना है। मेरे लिए, का उपयोग कर headबनाता है ज्यादा से ज्यादा समझ grepहै, क्योंकि बाद जिस तरह से अधिक जटिल है। मैं यह नहीं कह रहा हूं कि " grepधीमा है", यह वास्तव में नहीं है, लेकिन मुझे आश्चर्य होगा अगर यह headइस मामले की तुलना में तेज है । यह headमूल रूप से एक बग होगा ।


2
जब तक बाइट्स में लाइनें निर्धारित नहीं होती हैं, तब तक आपको यह नहीं पता होता है कि फ़ाइल के प्रारंभ से नई लाइन वर्णों की गिनती के बिना फ़ाइल पॉइंटर को कहाँ स्थानांतरित किया जाए।
जोसेफ वासना

यह प्रश्न का उत्तर प्रदान नहीं करता है। किसी लेखक से स्पष्टीकरण मांगने या उसका अनुरोध करने के लिए, उनके पोस्ट के नीचे एक टिप्पणी छोड़ दें।
प्रातः

@exhuma तुम सही हो। मैंने फिर से लिखा। सात साल पहले मुझे मिला था। :)
खोलना

20

व्हाट अबाउट:

tail -n +347340107 filename | head -n 100

मैंने इसका परीक्षण नहीं किया, लेकिन मुझे लगता है कि यह काम करेगा।


नहीं, आमतौर पर पूंछ में संस्करण और OS के आधार पर 256 अंतिम किलोबाइट या समान की सीमा होती है।
एंट्टी रित्सला

Ay यिसायर मिलर
dctremblay

13

मैं सिर्फ lessऔर में जाना पसंद करता हूं

  • 50%फ़ाइल को आधा करने के लिए टाइपिंग ,
  • 43210G 43210 लाइन पर जाने के लिए
  • :43210 वही करना

और इस तरह से सामान।

इससे भी बेहतर: vसंपादन शुरू करने के लिए मारा (निश्चित रूप से, उस स्थान पर!)। अब, ध्यान दें कि vimएक ही कुंजी बाइंडिंग है!


12

मैं पहले इस तरह से फ़ाइल को कुछ छोटे लोगों में विभाजित करता हूँ

$ split --lines=50000 /path/to/large/file /path/to/output/file/prefix

और फिर परिणामी फ़ाइलों पर grep।


सहमत हुए, कि लॉग अप करें और ठीक से ऐसा करने के लिए क्रॉन जॉब बनाएं। उन्हें इतना बड़ा होने से बचाए रखने के लिए लॉगरोट या कुछ समान का उपयोग करें।
तंज

9

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

  • एक पंक्ति प्रदर्शित करें (उदाहरण के लिए दूसरा):

    ex +2p -scq file.txt

    इसी सेड सिंटैक्स: sed -n '2p' file.txt

  • लाइनों की सीमा (जैसे 2-5 लाइनें):

    ex +2,5p -scq file.txt

    सीड सिंटैक्स: sed -n '2,5p' file.txt

  • दिए गए लाइन से अंत तक (जैसे फ़ाइल के अंत में 5):

    ex +5,p -scq file.txt

    सीड सिंटैक्स: sed -n '2,$p' file.txt

  • कई लाइन रेंज (जैसे 2-4 और 6-8 लाइनें):

    ex +2,4p +6,8p -scq file.txt

    सीड सिंटैक्स: sed -n '2,4p;6,8p' file.txt

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

seq 1 20 > file.txt

स्पष्टीकरण:

  • +या -cउसके बाद कमांड - फ़ाइल पढ़े जाने के बाद (vi / vim) कमांड निष्पादित करें,
  • -s - मूक मोड, एक डिफ़ॉल्ट आउटपुट के रूप में वर्तमान टर्मिनल का भी उपयोग करता है,
  • qइसके बाद -cएडिटर को छोड़ने की कमांड है (Add !to do force force, उदा -scq!)।

6

अगर आपका लाइन नंबर 100 पढ़ने के लिए है

head -100 filename | tail -1

6

प्राप्त ack

Ubuntu / डेबियन स्थापित करें:

$ sudo apt-get install ack-grep

फिर भागो:

$ ack --lines=$START-$END filename

उदाहरण:

$ ack --lines=10-20 filename

से $ man ack:

--lines=NUM
    Only print line NUM of each file. Multiple lines can be given with multiple --lines options or as a comma separated list (--lines=3,5,7). --lines=4-7 also works. 
    The lines are always output in ascending order, no matter the order given on the command line.

1
यह मेरे लिए ऐसा लगता है कि यहां सभी उत्तरों में से सबसे सहज वाक्यविन्यास के साथ कमांड है।
nnn

10 जनवरी, 2019 को संस्करण 2.999_06 से --linesपैरामीटर हटा दिया गया है।
Burny

4

लाइनों को गिनने के लिए sed को डेटा भी पढ़ना होगा। जिस तरह से एक शॉर्टकट संभव होगा, उस पर काम करने के लिए फ़ाइल में संदर्भ / आदेश होना चाहिए। उदाहरण के लिए अगर वहाँ लॉग एक निश्चित चौड़ाई समय / तिथि आदि आप इस्तेमाल कर सकते हैं के साथ prepended लाइनों थे नज़र विशेष दिनांक / समय के लिए फ़ाइलों के माध्यम से द्विआधारी खोज करने के लिए यूनिक्स उपयोगिता


4

उपयोग

x=`cat -n <file> | grep <match> | awk '{print $1}'`

यहां आपको लाइन नंबर मिलेगा जहां मैच हुआ था।

अब आप 100 लाइनों को प्रिंट करने के लिए निम्न कमांड का उपयोग कर सकते हैं

awk -v var="$x" 'NR>=var && NR<=var+100{print}' <file>

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

sed -n "${x},${x+100}p" <file>

यदि आपके पास एक से अधिक मैच हैं, तो पहले मैच के लिए "awk 'NR == 1 {प्रिंट $ 1}" का उपयोग करें
रमना रेड्डी

2

साथ sed -e '1,N d; M q'आप लाइनों प्रिंट करेंगे एन 1 एम इस के माध्यम से शायद थोड़ा बेहतर तो है grep -C, क्योंकि यह एक पैटर्न के लिए लाइनों मिलान करने का प्रयास नहीं करता है।


-eयहाँ वैकल्पिक है।
flow2k

2

Sklivvz के उत्तर पर निर्माण, यहाँ एक अच्छा कार्य एक .bash_aliasesफ़ाइल में रखा जा सकता है । फ़ाइल के सामने से सामान प्रिंट करते समय यह बड़ी फ़ाइलों पर कुशल है।

function middle()
{
    startidx=$1
    len=$2
    endidx=$(($startidx+$len))
    filename=$3

    awk "FNR>=${startidx} && FNR<=${endidx} { print NR\" \"\$0 }; FNR>${endidx} { print \"END HERE\"; exit }" $filename
}

1

इसके <textfile>द्वारा एक लाइन प्रदर्शित करने के लिए <line#>, बस यह करें:

perl -wne 'print if $. == <line#>' <textfile>

यदि आप नियमित अभिव्यक्ति के साथ लाइनों की एक श्रृंखला दिखाने के लिए अधिक शक्तिशाली तरीका चाहते हैं - मैं यह नहीं कहूंगा कि ऐसा करने के लिए grep एक बुरा विचार क्यों है, यह काफी स्पष्ट होना चाहिए - यह सरल अभिव्यक्ति आपको अपनी सीमा दिखाएगा सिंगल पास जो आप चाहते हैं कि ~ 20GB टेक्स्ट फ़ाइलों के साथ काम करते समय:

perl -wne 'print if m/<regex1>/ .. m/<regex2>/' <filename>

(टिप: यदि आपका रेगेक्स इसमें /है, तो m!<regex>!इसके बजाय कुछ का उपयोग करें )

यह <filename>उस रेखा से शुरू होता है जो उस रेखा से मेल खाती है <regex1>(और शामिल होती है) जो उस रेखा से मेल खाती है <regex2>

यह देखने के लिए एक जादूगर नहीं लेता है कि कैसे कुछ ट्विक्स इसे और अधिक शक्तिशाली बना सकते हैं।

अंतिम बात: पर्ल, चूंकि यह एक परिपक्व भाषा है, गति और प्रदर्शन के पक्ष में कई छिपी हुई वृद्धि है। इसे ध्यान में रखते हुए, यह इस तरह के एक ऑपरेशन के लिए स्पष्ट विकल्प बनाता है क्योंकि यह मूल रूप से बड़ी लॉग फ़ाइलों, पाठ, डेटाबेस आदि को संभालने के लिए विकसित किया गया था।


वास्तव में, यह मेरे लिए ऐसा नहीं लगता है, जब से एक पर्ल कमांड कह रहा है की तुलना में अधिक जटिल चल रहा है, 2+ प्रोग्राम एक साथ (पृष्ठ नीचे) पाइप चल रहा है, और, मुझे लगता है कि आप वास्तव में कह रहे हैं क्योंकि मैंने अधिक टाइप किया है एक स्पष्टीकरण जो आपको READ करने की आवश्यकता है, क्योंकि पेज के नीचे समान रूप से जटिल (या अधिक) हैं जो पानी से बाहर नहीं निकले ... शीश
ओसिरिसगोत्र

ध्यान दें कि उपयोगकर्ता ने कई लाइनों के लिए कहा है - हालांकि आपका उदाहरण तुच्छ रूप से अनुकूलित किया जा सकता है।
स्कलिव्ज़


0

पर्ल के साथ आसान! यदि आप किसी फ़ाइल से पंक्ति 1, 3 और 5 प्राप्त करना चाहते हैं, तो / etc / passwd कहें:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

1
आप कहते हैं कि यह जाग के साथ आसान है, लेकिन आपने इसके बजाय पर्ल में किया है?
कैदी 13

0

मैं केवल एक अन्य उत्तर (रमाना रेड्डी द्वारा) को आश्चर्यचकित करता हूं कि आउटपुट में लाइन नंबर जोड़ने का सुझाव दिया। निम्न आवश्यक पंक्ति संख्या की खोज करता है और आउटपुट को रंग देता है।

file=FILE
lineno=LINENO
wb="107"; bf="30;1"; rb="101"; yb="103"
cat -n ${file} | { GREP_COLORS="se=${wb};${bf}:cx=${wb};${bf}:ms=${rb};${bf}:sl=${yb};${bf}" grep --color -C 10 "^[[:space:]]\\+${lineno}[[:space:]]"; }

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