मेरे पास फ़ाइल के अंत में रिक्त लाइनों के साथ एक फ़ाइल है। क्या मैं 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
खाली पैटर्न अंतिम नियमित अभिव्यक्ति से मेल खाता है, जो कि कोई भी चरित्र था, इसलिए किसी भी गैर-खाली लाइन को संबोधित किया जाता है और संग्रहित लाइनों को "रीसेट" करने के लिए कमांड द्वारा पकड़ स्थान पर ले जाया जाता है। h
1. जब अगली खाली लाइन को जोड़ दिया जाएगा, उम्मीद के मुताबिक फिर से दो होंगे।$!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