टेक्स्ट फ़ाइल में nth कॉलम लें


86

मेरे पास एक टेक्स्ट फाइल है:

1 Q0 1657 1 19.6117 Exp
1 Q0 1410 2 18.8302 Exp
2 Q0 3078 1 18.6695 Exp
2 Q0 2434 2 14.0508 Exp
2 Q0 3129 3 13.5495 Exp

मैं हर पंक्ति का दूसरा और चौथा शब्द इस तरह लेना चाहता हूं:

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

मैं इस कोड का उपयोग कर रहा हूं:

 nol=$(cat "/path/of/my/text" | wc -l)
 x=1
 while  [ $x -le "$nol" ]
 do
     line=($(sed -n "$x"p /path/of/my/text)
     echo ""${line[1]}" "${line[3]}""  >> out.txt
     x=$(( $x + 1 ))
 done

यह काम करता है, लेकिन यह बहुत जटिल है और लंबी पाठ फ़ाइलों को संसाधित करने में लंबा समय लेता है।

क्या ऐसा करने का एक सरल तरीका है?


1
हर पंक्ति के 2 शब्द को 2 कॉलम कहा जाता है!
बर्नार्ड

जवाबों:


127

iirc:

cat filename.txt | awk '{ print $2 $4 }'

या, जैसा कि टिप्पणियों में बताया गया है:

awk '{ print $2 $4 }' filename.txt

16
UUOC !!! awk '{print $2,$4}' filename.txtबेहतर है (कोई पाइप नहीं, सिर्फ एक कार्यक्रम कहा जाता है)
नीला

5
@blue मैं अक्सर catफ़ाइल नाम निर्दिष्ट करने के बजाय अपनी बैश स्क्रिप्ट में उपयोग करता हूं, क्योंकि ओवरहेड न्यूनतम है और क्योंकि सिंटैक्स cat ... | ... > ...वास्तव में अच्छी तरह से दिखाता है कि इनपुट क्या है और आउटपुट कहां जाता है। हालांकि आप सही हैं, लेकिन वास्तव में यहां इसकी जरूरत नहीं है।
टॉम वैन डेर वोर्ड

8
@TomvanderWoerdt: मैं कभी-कभी < input awk '{ print $2 $4 }' > outputउस उद्देश्य के लिए लिखता हूं ।
ruakh

69

आप cutकमांड का उपयोग कर सकते हैं :

cut -d' ' -f3,5 < datafile.txt

प्रिंट

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

the

  • -d' '- मतलब, spaceएक सीमांकक के रूप में उपयोग करें
  • -f3,5 - 3rd और 5th कॉलम लें और प्रिंट करें

cutहै बहुत तेजी से एक शुद्ध खोल समाधान के रूप में बड़ी फ़ाइलों के लिए। यदि आपकी फ़ाइल कई व्हाट्सएप के साथ सीमांकित है, तो आप उन्हें पहले हटा सकते हैं, जैसे:

sed 's/[\t ][\t ]*/ /g' < datafile.txt | cut -d' ' -f3,5

जहाँ (ग्नू) सेड किसी एकल के साथ किसी वर्ण tabया spaceवर्ण को प्रतिस्थापित करेगा space

एक संस्करण के लिए - यहाँ एक पर्ल समाधान भी है:

perl -lanE 'say "$F[2] $F[4]"' < datafile.txt

1
अच्छी तरह से काम करता है ... यदि आप प्रत्येक पंक्ति पर रिक्त स्थान की संख्या की गारंटी दे रहे हैं, ... :)
rogerdpack

24

परिपूर्णता के लिए:

while read _ _ one _ two _; do
    echo "$one $two"
done < file.txt

इसके बजाय _एक मनमाना चर (जैसे junk) का भी उपयोग किया जा सकता है। बिंदु केवल कॉलम निकालने के लिए है।

डेमो:

$ while read _ _ one _ two _; do echo "$one $two"; done < /tmp/file.txt
1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

बिल्डरों द्वारा एक शेल में अच्छा, पठनीय, और कोई पर्ल्स / वेक्स / अन्य की आवश्यकता नहीं है।
पेट्र मटूसू

6

एक और सरल संस्करण -

$ while read line
  do
      set $line          # assigns words in line to positional parameters
      echo "$3 $5"
  done < file

4

यदि आपकी फ़ाइल में n लाइनें हैं, तो आपकी स्क्रिप्ट को फ़ाइल को n बार पढ़ना होगा ; इसलिए यदि आप फ़ाइल की लंबाई को दोगुना करते हैं, तो आप अपनी स्क्रिप्ट के काम की मात्रा को चौगुना कर देते हैं - और लगभग सभी काम बस फेंक दिया जाता है, क्योंकि आप जो करना चाहते हैं वह क्रम में लाइनों पर लूप है।

इसके बजाय, लूप का उपयोग करने का सबसे अच्छा तरीका एक whileलूप का उपयोग करना है, जिसमें कंडीशन-कमांड readबिलिन है:

while IFS= read -r line ; do
    # $line is a single line of the file, as a single string
    : ... commands that use $line ...
done < input_file.txt

आपके मामले में, चूंकि आप लाइन को एक सरणी में विभाजित करना चाहते हैं, और readबिलियन को वास्तव में एक सरणी चर को आबाद करने के लिए विशेष समर्थन है, जो कि आप चाहते हैं, आप लिख सकते हैं:

while read -r -a line ; do
    echo ""${line[1]}" "${line[3]}"" >> out.txt
done < /path/of/my/text

या बेहतर अभी तक:

while read -r -a line ; do
    echo "${line[1]} ${line[3]}"
done < /path/of/my/text > out.txt

हालाँकि, आप जो कर रहे हैं उसके लिए आप केवल cutउपयोगिता का उपयोग कर सकते हैं :

cut -d' ' -f2,4 < /path/of/my/text > out.txt

(या awk, जैसा कि टॉम वैन डेर वोर्ड्ट सुझाव देता है, या perl, या sed)।


readअधिक पसंद करेंगे cutक्योंकि यह खेतों के बीच कई रिक्त स्थान के खिलाफ मजबूत है और आपको सरणी जादू की आवश्यकता नहीं है:while read word1 word2 word3 word4 rest; do doSomethingWith $word2 $word4; done
user829755

3

यदि आप संरचित डेटा का उपयोग कर रहे हैं, तो इसे चलाने trऔर / cutया कुछ और करने के लिए एक अतिरिक्त शेल प्रक्रिया को लागू नहीं करने का अतिरिक्त लाभ है। ...

(बेशक, आप सशर्त और समझदार विकल्पों के साथ खराब इनपुट से बचना चाहेंगे।)

...
while read line ; 
do 
    lineCols=( $line ) ;
    echo "${lineCols[0]}"
    echo "${lineCols[1]}"
done < $myFQFileToRead ; 
...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.