बिल्ली कमांड से पहले X अक्षर प्राप्त करें?


42

मेरे पास एक पाठ फ़ाइल है जो मैं अपनी शेल स्क्रिप्ट में एक चर पर आउटपुट कर रहा हूं। मुझे केवल पहले 50 पात्रों की आवश्यकता है।

मैंने उपयोग करने की कोशिश की है, cat ${filename} cut -c1-50लेकिन मैं पहले 50 पात्रों से कहीं अधिक मिल रहा हूं? यह cutलाइनों की तलाश के कारण हो सकता है (100% निश्चित नहीं), जबकि यह पाठ फ़ाइल एक लंबी स्ट्रिंग हो सकती है - यह वास्तव में निर्भर करता है।

वहाँ एक उपयोगिता है मैं एक catकमांड से पहले एक्स अक्षर पाने के लिए पाइप कर सकता हूं ?


10
आप भूल गए |? cat ${filename} | cut -c1-50
डिस्प्लेनेम

@DisplayName तय है, मेरी पुनः प्राप्ति त्रुटि पकड़ने के लिए धन्यवाद।
jjj2000 18

1
@ jkj2000, मैं पुराने संस्करण पर वापस लौट आया हूं क्योंकि यह मूल प्रश्न था।
रमेश

जवाबों:


61
head -c 50 file

यह पहले 50 बाइट देता है।

ध्यान रखें कि कमांड हमेशा सभी ओएस पर समान रूप से लागू नहीं किया जाता है। लिनक्स और macOS पर यह इस तरह से व्यवहार करता है। सोलारिस (11) पर आपको gn वर्जन / usr / gnu / bin / का उपयोग करने की आवश्यकता है


सिर के पास कोई -cविकल्प नहीं है। मैं इसके बजाय dd (1) के लिए जाऊंगा ।
मिराबिलोस

7
ध्यान दें कि यह उत्तर मानता है कि फ़ाइल में केवल ASCII वर्ण हैं, क्योंकि OP ने पहले X वर्णों के लिए कहा था, बाइट्स नहीं।
कैलिमो

2
@mirabilos यह पोर्टेबल नहीं हो सकता है, लेकिन मेरा संस्करण ( GNU coreutils 5.97) करता है।
योशियेरियन

1
-cहालांकि, POSIX एक वैध विकल्प के रूप में परिभाषित नहीं होता है , इसलिए यह निश्चित रूप से आपके स्थानीय वातावरण पर निर्भर है। unix.com/man-page/posix/1/head
जूल्स

1
@ कैलीमो हां, मुझे पता है, लेकिन मैंने 100 अक्षरों के साथ एक टेक्स्ट फ़ाइल बनाने की कोशिश की और फिर मेरी कमांड को चलाया और इसमें 50 अक्षर छपे। लेकिन आप ASCII के बारे में सही हैं, लेकिन जब से ओपी ने इस बात का जवाब दिया कि उनके मामले में कोई नहीं था।
डिस्प्लेनेम

27

cutयदि आप डेटा को पास करने के लिए पाइप का उपयोग करते हैं तो आपकी कमांड काम करती है:

cat ${file} | cut -c1-50 

या, बिल्ली के बेकार उपयोग से बचें और इसे थोड़ा सुरक्षित करें:

cut -c1-50 < "$file"

ध्यान दें कि ऊपर दिए गए आदेश प्रत्येक इनपुट लाइन के पहले 50 अक्षरों (या आपके cutकार्यान्वयन के आधार पर बाइट्स ) को प्रिंट करेंगे । यह वही करना चाहिए जो आप उम्मीद करते हैं, जैसा कि आप कहते हैं, आपकी फ़ाइल एक बड़ी लाइन है।


8
dd status=none bs=1 count=50 if=${filename}

यह पहले 50 बाइट देता है।


dd का कोई status=noneझंडा नहीं है । 2>/dev/nullइसके बजाय का उपयोग करें (और ठीक से उद्धरण): dd if="$filename" bs=1 count=50 2>/dev/null(यहां तक ​​कि, bs=50 count=1शामिल syscalls की संख्या को कम करने के लिए उपयोग करने पर विचार करें )।
मिराबिलोस

1
@mirabilos dd के पास status=noneUbuntu 14.04, कोरुटिल्स 8.21 का उपयोग करते समय होता है , लेकिन यदि आप 2>/dev/nullपहले वाले संस्करण का उपयोग कर रहे हैं तो इसका उपयोग करना सही है ।
doneal24

1
@mirabilos अधिकांश लिनक्स डिस्ट्रोस GNU कोर्यूटिल्स का उपयोग करते हैं जैसा कि FreeBSD और अन्य BSD करता है। यह सोलारिस पर पैकेज ग्नू-कोरुटिल्स के रूप में उपलब्ध है। हां, यह "यूनिक्स और लिनक्स" है और यूनिक्स और लिनक्स दोनों सिस्टम GNU कोरुटिल्स का उपयोग करते हैं।
doneal24

2
नहीं, यूनिक्स सिस्टम आमतौर पर GNU उपयोगिताओं का उपयोग नहीं करते हैं। GNU "GNU यूनिक्स नहीं है" के लिए एक संक्षिप्त रूप है। कृपया पोर्टेबल समाधानों से चिपके रहें, या, यदि आपको GNU- केवल समाधान देना चाहिए , तो राज्य और, यदि संभव हो तो, एक बराबर पोर्टेबल समाधान दिखाएं।
mirabilos

1
कड़ाई से बोलते हुए, कि read()50 बाइट्स में से एक करता है । यदि fileउदाहरण के लिए एक पाइप है और समय पर कम वर्ण उपलब्ध हैं, तो कम बाइट्स वापस आ जाएंगे। के बराबर होने के लिए head -c50, आपको जीएनयू विशिष्ट का उपयोग करना होगा iflag=fullblock
स्टीफन चेजलस

4

अब तक के अधिकांश उत्तर यह मानते हैं कि 1 बाइट = 1 वर्ण, जो कि यदि आप एक गैर- ASCII लोकेल का उपयोग कर रहे हैं तो ऐसा नहीं हो सकता है।

इसे करने के लिए थोड़ा और मजबूत तरीका:

testString=$(head -c 200 < "${filename}") &&
  printf '%s\n' "${testString:0:50}"

ध्यान दें कि यह मानता है:

  1. आप उपयोग कर रहे हैं ksh93, bash(या हाल ही में zshया mksh(हालांकि केवल बहु-बाइट चारसेट द्वारा समर्थित mkshयूटीएफ -8 और उसके बाद set -o utf8-mode)) और headउस समर्थन का एक संस्करण -c(आजकल सबसे ज्यादा है, लेकिन सख्ती से मानक नहीं)।
  2. वर्तमान स्थान फ़ाइल के समान एन्कोडिंग पर सेट है (प्रकार locale charmapऔर file -- "$filename"उस की जांच करने के लिए); यदि नहीं, तो इसके साथ सेट करें। LC_ALL=en_US.UTF-8)
  3. मैंने headसबसे खराब स्थिति वाले UTF-8 को संभालने के साथ फ़ाइल के पहले 200 बाइट्स लिए , जहाँ सभी वर्णों को अधिकतम 4 बाइट्स पर एन्कोड किया गया है। मुझे उन अधिकांश मामलों को कवर करना चाहिए जिनके बारे में मैं सोच सकता हूं।

बेशक, यह GNU head, या इसके एक और कार्यान्वयन को मानता है जो n -n-standard -cविकल्प जोड़ता है । लेकिन आपको पहले से ही जीएनयू बैश की आवश्यकता है। (नोट: mkshUTF-8 मोड UTF-8 एन्कोडेड फ़ाइलों के लिए ऐसा कर सकता है।) मैं ओपी से पूछूंगा कि क्या उन्हें ओकटेट या मल्टीबाइट पात्रों की आवश्यकता है, बस "वर्ण" एक अस्पष्ट / सरस शब्द है।
mirabilos

वह भी मानता है $filenameया $testStringरिक्त newline या वाइल्डकार्ड शामिल नहीं है या के साथ शुरू -
स्टीफन चेजलस

यहां ${var:offset:length}आपके द्वारा उपयोग किया जा रहा निर्माण वास्तव में आता है ksh93और हाल के संस्करणों zsh( zshजिसका अपना है $testString[1,50]) द्वारा भी समर्थित है । आप की जरूरत ${testString:0:50} में ksh93और zshफिर भी।
स्टीफन चेजलस

बस ऊपर दिए गए टिप्पणियों को संबोधित करने के लिए मेरे जवाब को संपादित किया
कैलिमो

2
grep -om1 "^.\{50\}" ${filename}

अन्य संस्करण (फ़ाइल में पहली पंक्ति के लिए)

(IFS= read -r line <${filename}; echo ${line:0:50})

यह उच्च-स्तरीय औजारों का दुरुपयोग है - और आप जो चाहते हैं, वह करने की संभावना नहीं है, जैसे कि वे स्थानीय-जागरूक हों।
मिराबिलोस

@mirabilos उच्च-स्तरीय टूल के तहत आपका क्या मतलब है : readऔर echo? या bash expansion?
कोस्टा

grep(regexp), और हाँ, शेल का उपयोग यहाँ (संकेत: पहली पंक्ति बड़ी हो सकती है)। (यह कहा जा रहा है, बाशिस्म भी POSIX में नहीं है, लेकिन अधिकांश गोले इसे लागू करते हैं।)
मिराबिलोस

0

1. ASCII फ़ाइलों के लिए , @DisplayName कहते हैं:

head -c 50 file.txt

उदाहरण के लिए, file.txt के पहले 50 वर्णों को प्रिंट करेगा।

2. बाइनरी डेटा के लिए, hexdumpइसे हेक्स वर्ण के रूप में प्रिंट करने के लिए उपयोग करें:

hexdump -n 50 -v file.bin

उदाहरण के लिए file.bin के पहले 50 बाइट का प्रिंट आउट लेंगे।

ध्यान दें कि -vक्रिया विकल्प के बिना , hexdumpदोहराया लाइनों को तारांकन ( *) के बजाय बदल देगा। यहां देखें: https://superuser.com/questions/494245/what-does-an-asterisk-mean-in-hexdump-output/494613#494613


-2

आप इसके लिए sed का उपयोग कर सकते हैं जो समस्या से बहुत आसानी से निपटेगा

sed -e 's/^\(.\{50\}\).*/\1/' yourfile

यह जानने के लिए उत्सुक है कि अगर यह ओपी के प्रश्न को हल करता है तो यह कैसे खराब हो गया: "मुझे केवल पहले 50 पात्रों की आवश्यकता है" यह इस बात को पूरा करता है कि यूयूओसी के बिना क्या अनुरोध किया गया था (बेकार उपयोग बिल्ली)
munkeyoto

1
यह उत्तर फ़ाइल में प्रत्येक पंक्ति के पहले पचास अक्षरों को देता है, न कि फ़ाइल के पहले 50 को। यदि सभी लाइनें 50 वर्णों से कम लंबी हों तो भी कुछ भी प्रिंट नहीं करता है। आपका समाधान बेहतर होगाsed -n -e '1s/^\(.\{50\}\).*/\1/p' ${filename}
doneal24

समझ में आ सकता है बस: हेड-एन 1 | sed -e 's / ^ (।। {{50 \})। * / \ 1 /' ... और इससे समस्या हल हो जाती। ओपी ने कहा: "केवल पहले 50 पात्रों की आवश्यकता है"
munkeyoto

1
नहीं। यदि पहली पंक्ति केवल 49 वर्णों की है तो यह कुछ भी उत्पादन नहीं करेगी।
doneal24

डौग मैं यह पहली बार के आसपास समझ में आया अभी तक ओपी ने छपाई के बारे में कुछ भी नहीं बताया अगर लाइन में 50 से कम वर्ण होते हैं, तो मैं अभी भी आपकी बात को देखने में विफल हूं, और न ही इस के बिंदु को तब तक नीचा दिखाया जा सकता है जब तक कि इसमें क्या काम होता है सिर: सिर-एन 1 $ {फ़ाइल नाम} | sed -n -e '1s / ^ (। \ {50 \})। * / \ 1 / p'
munkeyoto
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.