मेरे पास फ़ाइल के अंत में रिक्त लाइनों के साथ एक फ़ाइल है। क्या मैं grepफ़ाइल के नाम पर स्क्रिप्ट के चर के रूप में फ़ाइल नाम के साथ रिक्त लाइनों की संख्या की गणना कर सकता हूं ?
grepमेरी किताब में पवित्रता के लिए @MichaelJohn के लिए कहा ।
मेरे पास फ़ाइल के अंत में रिक्त लाइनों के साथ एक फ़ाइल है। क्या मैं grepफ़ाइल के नाम पर स्क्रिप्ट के चर के रूप में फ़ाइल नाम के साथ रिक्त लाइनों की संख्या की गणना कर सकता हूं ?
grepमेरी किताब में पवित्रता के लिए @MichaelJohn के लिए कहा ।
जवाबों:
यदि रिक्त रेखाएं केवल अंत में हैं
grep -c '^$' myFile
या:
grep -cx '' myFile
grep -cv . myFileइसे लिखने का एक और तरीका है (कोड गोल्फ़र्स के लिए)। लेकिन मुझे एक हल मिला grepकि अगर फाइल में कहीं भी खाली लाइनें हैं।
grep -cv .उन लाइनों को भी गिनाएगा जिनमें केवल बाइट्स होते हैं जो वैध वर्ण नहीं बनाते हैं।
बस मज़े के लिए, कुछ डरावना sed:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
स्पष्टीकरण:
/./किसी भी वर्ण के साथ पंक्तियों को संबोधित करता है, इसलिए /./!गैर-रिक्त लाइनों को संबोधित करता है; उन लोगों के लिए, Hकमांड ने उन्हें होल्ड स्पेस में जोड़ा। इस प्रकार, यदि प्रत्येक खाली रेखा के लिए हमने होल्ड लाइन में एक लाइन जोड़ दी है, तो हमेशा खाली लाइनों की संख्या की तुलना में एक और रेखा होती है। हम बाद में उसकी देखभाल करेंगे।//hखाली पैटर्न अंतिम नियमित अभिव्यक्ति से मेल खाता है, जो कि कोई भी चरित्र था, इसलिए किसी भी गैर-खाली लाइन को संबोधित किया जाता है और संग्रहित लाइनों को "रीसेट" करने के लिए कमांड द्वारा पकड़ स्थान पर ले जाया जाता है। h1. जब अगली खाली लाइन को जोड़ दिया जाएगा, उम्मीद के मुताबिक फिर से दो होंगे।$!dस्क्रिप्ट को बिना आउटपुट के हर अंतिम पंक्ति के लिए रोक देता है, इसलिए आगे की आज्ञाओं को अंतिम पंक्ति के बाद ही निष्पादित किया जाता है। इसलिए जो भी खाली लाइनें हमने होल्ड स्पेस में एकत्र की हैं, वे फाइल के अंत में हैं। अच्छा।//d: dकमांड को केवल गैर-रिक्त लाइनों के लिए फिर से निष्पादित किया जाता है। इसलिए यदि अंतिम पंक्ति खाली नहीं थी, sedतो बिना किसी आउटपुट के बाहर निकल जाएगी। शून्य रेखाएँ। अच्छा।x एक्सचेंज स्पेस और पैटर्न स्पेस रखते हैं, इसलिए एकत्रित लाइनों को प्रोसेस करने के लिए अब पैटर्न स्पेस में हैं।s/\n//।wc -l।कुछ और जीएनयू tac/ tail -rविकल्प:
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
या:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
ध्यान दें कि आउटपुट पर:
printf 'x\n '
यही है, जहां अंतिम पूर्ण पंक्ति के बाद एक अतिरिक्त स्थान है (जो कुछ अतिरिक्त ब्लैंक लाइन के रूप में विचार कर सकते हैं, लेकिन पाठ की POSIX परिभाषा द्वारा, मान्य पाठ नहीं है), वे 0 देंगे।
POSIXly:
awk 'NF{n=NR};END{print NR-n}' < file
लेकिन इसका मतलब है कि फ़ाइल को पूर्ण रूप से पढ़ना ( tail -r/ खोज tacयोग्य फ़ाइलों पर फ़ाइल को पीछे से पढ़ना होगा)। 1के आउटपुट पर देता है printf 'x\n '।
जैसा कि आप वास्तव में एक grepसमाधान के लिए पूछ रहे हैं मैं इसे केवल जीएनयू पर निर्भर करता हूं grep(ठीक है, शेल सिंटैक्स और echo... का उपयोग करके भी ):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
मैं यहां क्या कर रहा हूं? $(grep -c ".*" "$1")फ़ाइल में सभी लाइनों को गिना जाता है, फिर हम खाली लाइनों को पीछे छोड़ते हुए फ़ाइल को हटा देते हैं।
और वे कैसे प्राप्त करें? $(grep -B42 . "$1"सभी गैर-खाली लाइनों और उनके सामने 42 लाइनों को पकड़ना होगा, इसलिए यह अंतिम गैर-खाली रेखा तक सब कुछ प्रिंट करेगा, जब तक कि गैर-खाली लाइन से पहले लगातार 42 से अधिक खाली लाइनें न हों। उस सीमा से बचने के लिए, मैं विकल्प $(grep -cv . "$1")के पैरामीटर के रूप में लेता हूं -B, जो कि खाली लाइनों की कुल संख्या है, इसलिए हमेशा पर्याप्त बड़ी होती है। इस तरह मैंने अनुगामी खाली लाइनों को छीन लिया है और लाइनों |grep -c ".*"को गिनने के लिए उपयोग कर सकते हैं ।
शानदार, है ना? (-;
tac | grepपहले गैर-रिक्त के साथ होगा -m -A 42, फिर एक शून्य से। मुझे यकीन नहीं है जो अधिक कुशल है, लेकिन आप wc -l | cut -d' ' -f1खाली लाइनों को टटोलने के बजाय भी कर सकते हैं ?
tac, wcऔर cut, लेकिन यहां मैंने खुद को प्रतिबंधित करने की कोशिश की grep। आप इसे विकृति कह सकते हैं, मैं इसे खेल कह सकता हूं। - (;
एक और awkउपाय। यह भिन्नता kहर बार गैर-रिक्त रेखा होने पर काउंटर को रीसेट करती है। फिर, हर पंक्ति काउंटर को बढ़ाती है। (इसलिए, पहली गैर-रिक्त लंबाई लाइन के बाद k==0।) अंत में हम उन पंक्तियों की संख्या को आउटपुट करते हैं जिन्हें हमने गिना है।
डेटा फ़ाइल तैयार करें
cat <<'X' >input.txt
aaa
bbb
ccc
X
नमूने में अनुगामी खाली लाइनों की गणना करें
awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3
इस परिभाषा में, रिक्त पंक्ति में रिक्त स्थान या अन्य रिक्त वर्ण हो सकते हैं; यह अभी भी खाली है। क्या तुम सच में करने के बजाय खाली लाइनों रिक्त लाइनों, परिवर्तन की गणना करना चाहते हैं NFके लिए $0 != ""।
$0 > ""? यही कारण है कि का उपयोग करता है strcoll()जो कम कुशल हो जाएगा की तुलना में $0 != ""जो का उपयोग करता है memcmp()कई कार्यान्वयन में (इसे POSIX उपयोग करने के लिए यह आवश्यक था strcoll(), हालांकि)।
$0 > ""अलग हो सकता है $0 != ""। मैं awkवैसे भी "धीमे" ऑपरेटर के रूप में व्यवहार करता हूं (जैसे कि अगर मुझे पता है कि मुझे इनपुट के रूप में एक बड़ा डेटासेट मिल गया है और प्रसंस्करण समय महत्वपूर्ण है, मैं देखूंगा कि राशि को कम करने के लिए मैं क्या कर सकता awkहूं - प्रक्रिया करने के लिए - मुझे grep | awkऐसी स्थितियों में निर्माण का इस्तेमाल किया है)। हालाँकि, मुझे लगता है मैं क्या या किसी भी संदर्भ नहीं देख सकते हैं POSIX परिभाषा है पर एक त्वरित लग रहा था । मुझे किसकी याद आ रही है? strcoll()memcmp()
strcoll()== स्ट्रिंग्स की तुलना स्थानीय-विशिष्ट कॉलेशन अनुक्रम का उपयोग करके की जाएगी । पिछले संस्करण से तुलना करें । मैं इसे लाने वाला था। यह भी देखें austingroupbugs.net/view.php?id=963
a <= b && a >= bआवश्यक रूप से समान नहीं है a == b। आउच!
awkया bash(इसके लिए [[ a < b ]]के लिए उदाहरण के लिए जीएनयू सिस्टम पर en_US.UTF-8 स्थानों में ऑपरेटरों) ①बनाम ②(उदाहरण के लिए के लिए bash, में से कोई भी <, >, =उन लोगों के लिए सच वापसी)। संभवतः यह उन स्थानों की परिभाषा में एक बग है जो बाश /
फ़ाइल के अंत में लगातार रिक्त लाइनों की संख्या की गणना करने के लिए
ठोस awk+ tacसमाधान:
नमूना input.txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
कार्य:
awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
!NF- यह सुनिश्चित करता है कि वर्तमान लाइन खाली है (कोई फ़ील्ड नहीं है)NR==++c- रिक्त लाइनों के निरंतर क्रम को सुनिश्चित करना। ( NR- रिकॉर्ड संख्या, ++c- समान रूप से बढ़ा हुआ सहायक काउंटर)cnt++- खाली लाइनों का काउंटरउत्पादन:
3
IIUC, निम्न स्क्रिप्ट कहलाता है count-blank-at-the-end.shकि यह काम करेगा:
#!/usr/bin/env sh
count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))
printf "%s\n" "$num_of_blank_lines"
उदाहरण का उपयोग:
$ ./count-blank-at-the-end.sh FILE
4
मैं इसे में परीक्षण किया GNU bash, Android mkshऔर में ksh।
वैकल्पिक Pythonसमाधान:
नमूना input.txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
कार्य:
python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt
उत्पादन:
3
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile