Bir metin dosyasında n'inci sütunu al


85

Bir metin dosyam var:

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

Her satırın 2. ve 4. kelimesini şöyle almak istiyorum:

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

Bu kodu kullanıyorum:

 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

Çalışır, ancak çok karmaşıktır ve uzun metin dosyalarını işlemek uzun zaman alır.

Bunu yapmanın daha basit bir yolu var mı?


1
Her satırın 2. kelimesi basitçe 2. sütun olarak adlandırılır!
Bernard

Yanıtlar:


127

iirc:

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

veya yorumlarda belirtildiği gibi:

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

16
UUOC !!! awk '{print $2,$4}' filename.txtdaha iyi (boru yok, sadece bir program çağrılıyor)
mavi

5
@blue Genellikle catbir dosya adı belirtmek yerine bash betiklerimde kullanırım, çünkü ek yük minimumdur ve sözdizimi cat ... | ... > ...gerçekten girdinin ne olduğunu ve çıktının nereye gittiğini gösterir. Yine de haklısın, aslında burada gerekli değil.
Tom van der Woerdt

8
@TomvanderWoerdt: Bazen < input awk '{ print $2 $4 }' > outputbu amaçla yazıyorum .
ruakh

68

Şu cutkomutu kullanabilirsiniz :

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

baskılar

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

the

  • -d' '- demek, spacesınırlayıcı olarak kullanın
  • -f3,5 - 3. ve 5. sütunu alın ve yazdırın

cutOlduğunu çok daha hızlı bir saf kabuk çözüm olarak büyük dosyalar için. Dosyanız birden çok boşlukla sınırlandırılmışsa, önce bunları kaldırabilirsiniz, örneğin:

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

burada (gnu) sed herhangi tabveya spacekarakterleri tek ile değiştirecektir space.

Bir varyant için - işte bir perl çözümü de:

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

1
İyi çalışıyor ... her satırda bu kadar boşluk garanti ediyorsanız, tam olarak ... :)
rogerdpack

24

Bütünlüğü uğruna:

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

_Keyfi bir değişken yerine (örneğinjunk ) da kullanılabilir. Önemli olan sadece sütunları çıkarmaktır.

Demo:

$ 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

Güzel, okunabilir ve perls / awks / diğerlerine gerek yok, hepsi yerleşik tarafından tek bir kabukta.
Petr Matousu

6

Daha basit bir varyant -

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

4

Dosyanız n satır içeriyorsa , komut dosyanızın n dosyasını okuması gerekir kez ; bu nedenle, dosyanın uzunluğunu iki katına çıkarırsanız, betiğinizin yaptığı iş miktarını dört katına çıkarırsınız ve neredeyse tüm bu iş bir kenara atılır, çünkü tek yapmak istediğiniz sırayla satırların üzerinden geçmektir.

Bunun yerine, bir dosyanın satırları üzerinde döngü yapmanın en iyi yolu while, koşul komutunun readyerleşik olduğu bir döngü kullanmaktır :

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

Sizin durumunuzda, çizgiyi bir diziye bölmek istediğinizden ve readyerleşik aslında bir dizi değişkenini doldurmak için özel desteğe sahip olduğundan, istediğiniz şey budur, yazabilirsiniz:

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

veya daha iyisi:

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

Ancak, yaptığınız şey için cutyardımcı programı kullanabilirsiniz :

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

(veya awkTom van der Woerdt'ın önerdiği gibi perl, veya hatta sed).


tercih ediyorum readüzerinde cut: o alanlar arasında birden çok boşluk karşı sağlam ve sen dizi sihirli gerekmez çünküwhile read word1 word2 word3 word4 rest; do doSomethingWith $word2 $word4; done
user829755

3

Yapılandırılmış veri kullanıyorsanız, bu, çalıştırmak trve / cutveya başka bir şey için fazladan bir kabuk işlemi başlatmama avantajına sahiptir . ...

(Elbette, koşullu ve mantıklı alternatiflerle kötü girdilere karşı korunmak isteyeceksiniz.)

...
while read line ; 
do 
    lineCols=( $line ) ;
    echo "${lineCols[0]}"
    echo "${lineCols[1]}"
done < $myFQFileToRead ; 
...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.