टेक्स्ट फ़ाइल की प्रत्येक पंक्ति में वर्णों की संख्या कैसे प्रिंट करें


83

मैं एक यूनिक्स कमांड का उपयोग करके टेक्स्ट फ़ाइल की प्रत्येक पंक्ति में वर्णों की संख्या प्रिंट करना चाहूंगा। मुझे पता है कि यह पॉवरशेल के साथ सरल है

gc abc.txt | % {$_.length}

लेकिन मुझे यूनिक्स कमांड की जरूरत है।

जवाबों:


155

आवक का उपयोग करें।

awk '{ print length }' abc.txt

2
यह प्रत्येक पंक्ति में wc -c लागू करने की तुलना में तेजी से परिमाण के कई आदेश हैं!
एरिजमैन

इस प्रकार की समस्याओं के लिए @Aerijman प्रक्रिया कृतियों की संख्या आमतौर पर वही है जो सबसे अधिक प्रदर्शन अंतर बनाती है।
मार्क डे

यदि फ़ाइल में एक पंक्ति में एमोजिस हैं तो यह अपेक्षित लंबाई नहीं पैदा करेगा।
user5507535

@ user5507535, यह इस बात पर निर्भर करता है कि आप वास्तव में किस "लंबाई" की उम्मीद करते हैं। यूनिकोड के लिए कई संभावित परिभाषाएं हैं (मॉक बाइट्स का उपयोग करता है, गौक की जांच नहीं करता है)।
Jan Hudec

16
while IFS= read -r line; do echo ${#line}; done < abc.txt

यह POSIX है, इसलिए इसे हर जगह काम करना चाहिए।

संपादित करें: विलियम द्वारा सुझाए गए अनुसार जोड़ा गया।

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

संपादित करें: IFS=अग्रणी और अनुगामी रिक्त स्थान खोने से बचने के लिए उपसर्ग ।


+1, लेकिन ... यदि इनपुट में '\' है तो यह विफल हो जाएगा।
वाच

यदि फ़ाइल में एक पंक्ति में एमोजिस हैं तो यह अपेक्षित लंबाई नहीं पैदा करेगा।
user5507535

@ user5507535, वास्तव में, यह उस "लंबाई" पर निर्भर करता है जो आप उम्मीद करते हैं। यूनिकोड के लिए कई संभावित परिभाषाएं हैं (लेकिन इस मामले में, अलग-अलग गोले वास्तव में अलग काम करेंगे)।
Jan Hudec

मनमानी डेटा में पढ़ने के लिए हमेशा कमांड IFS=पर सेट readकरें। तो IFS= read -r। शब्द विभाजन करने के लिए readउपयोग करता है IFS, और भले ही सभी विभाजित शब्द फिर से एक उपलब्ध चर ( line) में एक साथ चिपकाए जाते हैं, इस बात की कोई गारंटी नहीं है कि वे सभी मूल विभाजक वर्णों के साथ वापस चिपक जाते हैं जो उनके पास थे या सिर्फ एक संभावित रूप से अलग लोगों को। उदाहरण के लिए, डिफ़ॉल्ट IFS के साथ, लाइन foo barबन सकता है foo bar, 7 रिक्त स्थान खो सकता है । (जैसे कैसे स्टैक ओवरफ्लो ने इस टिप्पणी में उस उदाहरण स्ट्रिंग में आसन्न रिक्त स्थान खो दिया है)।
mtraceur

@mtraceur, प्रलेखन स्पष्ट रूप से कहता है कि "शेष शब्द और उनके बीच के परिसीमन को अंतिम नाम दिया गया है," इसलिए वे मूल विभाजक के साथ वापस चिपक जाते हैं। हालांकि, अग्रणी और पीछे चल रहे सीमांकक की देखभाल नहीं करता है, जो वास्तव में खो गए हैं। तो आप सही हैं, IFSसेट होना चाहिए, लेकिन समस्या यह नहीं है जब यह अधिक सूक्ष्म है।
Jan Hudec

4

मैंने ऊपर सूचीबद्ध अन्य उत्तरों की कोशिश की है, लेकिन बड़ी फ़ाइलों के साथ काम करते समय वे सभ्य समाधानों से बहुत दूर हैं - विशेष रूप से एक बार एक पंक्ति का आकार उपलब्ध रैम के ~ 1/4 से अधिक हो जाता है।

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

मैंने एक बहुत ही सरल, काफी अडॉप्टेड पाइथन स्क्रिप्ट को लागू किया है, जब बड़ी फ़ाइलों (~ 4 जीबी प्रति पंक्ति) के साथ परीक्षण किया जाता है, तो थप्पड़ नहीं पड़ता है, और अब तक दिए गए से बेहतर समाधान है।

यदि यह उत्पादन के लिए महत्वपूर्ण समय है, तो आप C में विचारों को फिर से लिख सकते हैं या रीड कॉल पर बेहतर अनुकूलन कर सकते हैं (केवल एक बार में एक बाइट पढ़ने के बजाय), परीक्षण के बाद कि यह वास्तव में एक अड़चन है।

कोड मानता है कि न्यूलाइन एक लाइनफीड चरित्र है, जो यूनिक्स के लिए एक अच्छी धारणा है, लेकिन मैक ओएस / विंडोज पर वाईएमएमवी। सुनिश्चित करें कि अंतिम पंक्ति वर्ण गणना को नजरअंदाज नहीं किया गया है यह सुनिश्चित करने के लिए फाइल एक लाइनफीड के साथ समाप्त होती है।

from sys import stdin, exit

counter = 0
while True:
    byte = stdin.buffer.read(1)
    counter += 1
    if not byte:
        exit()
    if byte == b'\x0a':
        print(counter-1)
        counter = 0

1
प्रश्न "पाठ" फ़ाइल के लिए था। मुझे नहीं लगता कि प्रति पंक्ति 4GB किसी पाठ फ़ाइल की कोई उचित परिभाषा है।
मार्ख

3

यहाँ उदाहरण का उपयोग कर रहा है xargs:

$ xargs -d '\n' -I% sh -c 'echo % | wc -c' < file

यह "इको%" असुरक्षित वर्णों को नहीं संभालता है जिन्हें शेल से उद्धृत करने की आवश्यकता होती है। इसके अलावा "xargs" रिक्त स्थान और newlines द्वारा आपकी फ़ाइल को विभाजित करने जा रहा है, न कि मूल रूप से अनुरोध किए गए पोस्टर के रूप में नईलाइन्स।
ग्वार

1

इसे इस्तेमाल करे:

while read line    
do    
    echo -e |wc -m      
done <abc.txt    

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