केवल शेल स्क्रिप्ट का उपयोग करके टेक्स्ट फ़ाइल से विशिष्ट लाइन प्राप्त करें


100

मैं एक पाठ फ़ाइल से एक विशिष्ट लाइन प्राप्त करने की कोशिश कर रहा हूं।

अब तक, ऑनलाइन मैंने केवल sed जैसे सामान देखे हैं, (मैं केवल sh -not bash या sed या ऐसा कुछ भी उपयोग कर सकता हूं)। मुझे केवल एक मूल शेल स्क्रिप्ट का उपयोग करके ऐसा करने की आवश्यकता है।

cat file | while read line
    do
       #do something
    done

मुझे पता है कि लाइनों के माध्यम से पुनरावृत्ति कैसे की जाती है, जैसा कि ऊपर दिखाया गया है, लेकिन क्या होगा अगर मुझे किसी विशेष लाइन की सामग्री प्राप्त करने की आवश्यकता है


क्या आप लाइन नंबर जानते हैं?
मेहुल राठौड़


जी हां, लाइन नंबर 5 @MehulRathod
GangstaGraham

3
क्यों catठीक है लेकिन sedनहीं है? इसका कोई अर्थ नही बन रहा है।
विलियम पर्ससेल

5
क्योंकि कोई भी नहीं कह सकता है cat। अजी ... प्यारा cat!

जवाबों:


204

sed:

sed '5!d' file

awk:

awk 'NR==5' file

श कमांड के बारे में क्या, मैं sed, awk का उपयोग नहीं कर सकता। मुझे प्रश्न में इसे और स्पष्ट करना चाहिए।
गंगस्थग्राम

@GangstaGraham आपने कहा था कि आप जानते हैं कि लाइनों के माध्यम से पुनरावृत्ति कैसे होती है, काउंटर जोड़ने के बारे में कैसे? यदि काउंटर आपके लक्ष्य रेखा संख्या तक पहुंचता है, तो लाइन प्राप्त करें और लूप को तोड़ दें। क्या इसने सहायता की?
केंट

4
@KanagaveluSugumar ने sed की जानकारी पृष्ठ को पढ़ा। 5!dइसका मतलब है कि 5. शेल वर्जन को छोड़कर सभी लाइनों को हटा दें, आपको दोहरे उद्धरण चिह्नों की आवश्यकता है।
केंट

13
मैं एक और संस्करण जोड़ने का सुझाव दूंगा: sed -n 5pयह newbies के लिए याद रखने के लिए अधिक तर्कसंगत लगता है, क्योंकि -nइसका मतलब है "डिफ़ॉल्ट रूप से कोई आउटपुट नहीं" और p"प्रिंट" के लिए खड़ा है, और हटाने का कोई संभावित भ्रामक उल्लेख नहीं है (जब लोग फाइलों के बारे में बात करते हैं, तो लाइनों को हटाने की प्रवृत्ति होती है। कुछ अलग मतलब)।
जोसिप रॉडिन

1
@JosipRodin आप सही हैं, -n '5p'इस समस्या के लिए भी काम करता है। यहां अंतर यह है कि, 5!dआप -iफ़ाइल में परिवर्तन को वापस लिखने के लिए जोड़ सकते हैं । हालांकि, के साथ -n 5pआप के लिए है sed -n '5p' f > f2&& mv f2 fफिर से, इस प्रश्न के लिए, मैं आपकी राय से सहमत हूँ।
कैंट

21

मान lineलेना एक चर है जो आपकी आवश्यक पंक्ति संख्या रखता है, यदि आप उपयोग कर सकते हैं headऔर tail, तो यह काफी सरल है:

head -n $line file | tail -1

यदि नहीं, तो यह काम करना चाहिए:

x=0
want=5
cat lines | while read line; do
  x=$(( x+1 ))
  if [ $x -eq "$want" ]; then
    echo $line
    break
  fi
done

यह -eqतुलना पूर्णांक के लिए है, इसलिए यह एक पंक्ति संख्या चाहता है, न कि पंक्ति सामग्री ( $line)। यह want=5लूप से पहले उदाहरण को परिभाषित करके तय किया जाना है , और फिर -eqतुलना का उपयोग करके $want। [खारिज किए गए संपादन से चले गए]
जोसिफ रोडिन

1
@JosipRodin मैंने आपकी टिप्पणी के आधार पर एक स्वतंत्र संपादन सुझाव दिया, जैसा कि मैं इससे सहमत हूं। उम्मीद है कि इस बार इसे खारिज नहीं किया जाएगा।
विक्टर ज़मानियन

15

आप उपयोग कर सकते हैं sed -n 5p file

आप एक सीमा भी प्राप्त कर सकते हैं, जैसे sed -n 5,10p file,।


11

सर्वश्रेष्ठ प्रदर्शन विधि

sed '5q;d' file

क्योंकि sed5 वीं के बाद किसी भी लाइन को पढ़ना बंद कर देता है

श्री रोजर ड्यूक से अद्यतन अद्यतन

मैंने wcanadian-insane (6.6MB) स्थापित किया और sed -n 1p / usr / share / तानाशाही / शब्दों और sed '1q; d' / usr / share / तानाशाही / शब्दों की तुलना समय कमांड का उपयोग करके की; पहले ने 0.043s लिया, दूसरा केवल 0.002 सेकेंड का, इसलिए 'q' का उपयोग करना निश्चित रूप से एक प्रदर्शन सुधार है!


1
यह भी आम तौर पर लिखा गया है:sed -n 5q
विलियम पर्ससेल

3
मुझे यह समाधान पसंद है क्योंकि sed5 वीं के बाद किसी भी लाइनों को पढ़ना बंद हो जाता है।
एंथनी जोगेगन

1
मैंने wcanadian-insane (6.6MB) स्थापित किया और कमांड की तुलना sed -n 1p /usr/share/dict/wordsऔर sed '1q;d' /usr/share/dict/wordsउपयोग किया time; पहले ने 0.043s लिया, दूसरा केवल 0.002 सेकेंड का, इसलिए 'q' का उपयोग करना निश्चित रूप से एक प्रदर्शन सुधार है!
रोजर ड्यूक

5

यदि उदाहरण के लिए आप एक फ़ाइल की 10 से 20 लाइनें प्राप्त करना चाहते हैं, तो आप इन दोनों विधियों में से प्रत्येक का उपयोग कर सकते हैं:

head -n 20 york.txt | tail -11

या

sed -n '10,20p' york.txt 

p ऊपर में आदेश मुद्रण के लिए खड़ा है।

यहाँ आप देख सकते हैं: यहां छवि विवरण दर्ज करें


2

इस तरह का काम करने का मानक तरीका बाहरी उपकरणों का उपयोग करना है। शेल स्क्रिप्ट लिखते समय बाहरी उपकरणों के उपयोग को अस्वीकार करना बेतुका है। हालाँकि, यदि आप वास्तव में बाहरी उपकरणों का उपयोग नहीं करना चाहते हैं, तो आप लाइन 5 को इसके साथ प्रिंट कर सकते हैं:

i=0; while read line; do test $((++i)) = 5 && echo "$line"; done < input-file

ध्यान दें कि यह तार्किक रेखा 5 को प्रिंट करेगा। अर्थात, यदि input-fileलाइन में निरंतरता है, तो उन्हें एक ही लाइन के रूप में गिना जाएगा। आप -rपढ़े गए आदेश में जोड़कर इस व्यवहार को बदल सकते हैं । (जो शायद वांछित व्यवहार है।)


1
$((++i))एक बाशिस्म प्रतीत होता है; यदि बाहरी उपकरणों के उपयोग में ओपी प्रतिबंधित है, तो मैं यह नहीं मानूंगा कि उनके पास एक सादे से अधिक का उपयोग होगा/bin/sh
जोसिप रोडिन

@ जोसिप्रोडिन नहीं, यह एक POSIX फीचर है (लेकिन ++वेतन वृद्धि के लिए समर्थन को विशेष रूप से वैकल्पिक के रूप में चिह्नित किया गया है)।
ट्रिपल

@tripleee यह आधुनिक डैश के साथ / बिन / श के रूप में काम नहीं करता है, इसलिए मैं इस पर भरोसा नहीं करता।
जोसिप रॉडिन

लेकिन $((i+=1))डैश में काम करने की तरह एक साधारण वर्कअराउंड भी।
ट्रिपल

$(($i+1))मैं जो सोच रहा था वह सरल है।
जोसिप रोडिन

1

विलियम पर्सल के जवाब के समानांतर , यहां एक सरल निर्माण है जो मूल v7 बॉर्न शेल में भी काम करना चाहिए (और इस तरह से उन स्थानों पर भी जहां बाश उपलब्ध नहीं है)।

i=0
while read line; do
    i=`expr "$i" + 1`
    case $i in 5) echo "$line"; break;; esac
done <file

breakजब हम उस लाइन को प्राप्त कर लेते हैं जिसे हम देख रहे थे, तो लूप से बाहर निकलने के लिए अनुकूलन को भी नोटिस करें ।


0

मुझे कोई उत्तर पसंद नहीं आया।

यहाँ देखें कि मैंने यह कैसे किया।

# Convert the file into an array of strings
lines=(`cat "foo.txt"`)

# Print out the lines via array index
echo "${lines[0]}"
echo "${lines[1]}"
echo "${lines[5]}"

-1

पर्ल के साथ आसान! यदि आप किसी फ़ाइल से पंक्ति 1, 3 और 5 प्राप्त करना चाहते हैं, तो / etc / passwd कहें:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

seq 5 | perl -ne 'print if $. ~~ [1, 4, 5]'लेकिन स्मार्टमैच प्रायोगिक है और यह हतोत्साहित है
सोरिन

अन्य समाधानों में से एक भी यह संक्षिप्त नहीं है, या यह बहुत अधिक लचीलेपन की अनुमति देता है। (ऐसा क्यों है कि सब कुछ है कि समय बचाता है और चीजों को आसान बना देता है, "स्मार्ट लोगों" से "हतोत्साहित" है प्रतीत होता है, हम सब पूरे दिन स्क्रीन पर टकटकी करने वाले हैं?)
dagelf

-1
line=5; prep=`grep -ne ^ file.txt | grep -e ^$line:`; echo "${prep#$line:}"

3
क्या आप कम से कम इसका वर्णन कर सकते हैं कि यह सवाल पूछने वाले को स्पष्ट करने के लिए क्यों काम करता है?
टेड

तो, पहला grep अपनी शुरुआत में लाइन नंबर जोड़ने वाली सभी लाइनों का चयन करता है। फिर दूसरा grep प्रारंभ में लाइन संख्या का मिलान करके एक विशिष्ट रेखा का चयन करता है। और अंत में ईको में लाइन स्टार्ट से लाइन नंबर को ट्रिम किया जाता है।
ओडर

यह दोनों की तुलना में जटिल और अक्षम है sed -n 5p, जो निश्चित रूप से अभी भी कुछ के लिए अनुकूलित किया जा सकता है जैसेsed -n '5!d;p;q'
ट्रिपल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.