फ़ाइल के अंत में रिक्त लाइनों की संख्या की गणना करें


11

मेरे पास फ़ाइल के अंत में रिक्त लाइनों के साथ एक फ़ाइल है। क्या मैं grepफ़ाइल के नाम पर स्क्रिप्ट के चर के रूप में फ़ाइल नाम के साथ रिक्त लाइनों की संख्या की गणना कर सकता हूं ?


लगातार रिक्त लाइनों की संख्या की गणना करने के लिए ?
रोमनप्रेह्रेस्ट

2
@RomanPerekhrest मैं ऐसा कहूंगा, अन्यथा वे "फ़ाइल के अंत में" नहीं होंगे?
स्पार्कहॉक

'grep -cv -P' \ S 'फ़ाइल नाम' फ़ाइल में कुल पंक्तियों की गिनती करेगा। अंत में संख्या केवल मेरे मस्तिष्क पर कर लगा रही है!
माइकलजॉन

ओपी ने grepमेरी किताब में पवित्रता के लिए @MichaelJohn के लिए कहा ।
bu5hman

2
@ bu5hman लेकिन (जैसा वह स्वीकार करता है) सवाल का जवाब नहीं देता है। और न ही तुम्हारा, वास्तव में।
स्पार्कहॉक

जवाबों:


11

यदि रिक्त रेखाएं केवल अंत में हैं

grep  -c '^$' myFile

या:

grep -cx '' myFile


grep -cv . myFileइसे लिखने का एक और तरीका है (कोड गोल्फ़र्स के लिए)। लेकिन मुझे एक हल मिला grepकि अगर फाइल में कहीं भी खाली लाइनें हैं।
फिलिप्पुस

2
@Philippos, grep -cv .उन लाइनों को भी गिनाएगा जिनमें केवल बाइट्स होते हैं जो वैध वर्ण नहीं बनाते हैं।
स्टीफन चेजेलस

11

बस मज़े के लिए, कुछ डरावना 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

8

कुछ और जीएनयू 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 '


6

जैसा कि आप वास्तव में एक 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 ".*"को गिनने के लिए उपयोग कर सकते हैं ।

शानदार, है ना? (-;


के रूप में +1 पूछा क्योंकि यद्यपि कि भयानक कोड है, यह तकनीकी रूप से सवाल का जवाब और मैं ;-) आप नीचे चिह्नित करने के लिए बर्दाश्त नहीं कर सकता
roaima

Grepmeister। हम योग्य नहीं हैं।
bu5hman

विकृति के लिए +1। एक और (संभवतः तेज?) विकल्प tac | grepपहले गैर-रिक्त के साथ होगा -m -A 42, फिर एक शून्य से। मुझे यकीन नहीं है जो अधिक कुशल है, लेकिन आप wc -l | cut -d' ' -f1खाली लाइनों को टटोलने के बजाय भी कर सकते हैं ?
स्पार्कहॉक

हां, निश्चित रूप से, आप बहुत सी चीजों के साथ कर सकते हैं tac, wcऔर cut, लेकिन यहां मैंने खुद को प्रतिबंधित करने की कोशिश की grep। आप इसे विकृति कह सकते हैं, मैं इसे खेल कह सकता हूं। - (;
फिलिप्पुस

5

एक और 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। आउच!
16:48 पर रोइमा

यही कारण है कि जीएनयू का मामला है awkया bash(इसके लिए [[ a < b ]]के लिए उदाहरण के लिए जीएनयू सिस्टम पर en_US.UTF-8 स्थानों में ऑपरेटरों) बनाम (उदाहरण के लिए के लिए bash, में से कोई भी <, >, =उन लोगों के लिए सच वापसी)। संभवतः यह उन स्थानों की परिभाषा में एक बग है जो बाश /
जाग

2

फ़ाइल के अंत में लगातार रिक्त लाइनों की संख्या की गणना करने के लिए

ठोस 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

1

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


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