テキストファイルのn番目の列を取得します


85

私はテキストファイルを持っています:

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

私はこのようにすべての行の2番目と4番目の単語を取りたいです:

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

ちゃんと覚えたら :

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

または、コメントで述べたように:

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

16
UUOC !!! awk '{print $2,$4}' filename.txtより良い(パイプなし、呼び出されるプログラムは1つだけ)

5
@bluecatオーバーヘッドが最小限であり、構文cat ... | ... > ...が入力と出力の行き先を非常にうまく示しているため、ファイル名を指定する代わりにbashスクリプトでよく使用します。あなたは正しいですが、実際にはここでは必要ありません。
Tom van der Woerdt 2013年

8
@TomvanderWoerdt:私は時々< input awk '{ print $2 $4 }' > outputその目的のために書きます。
ruakh 2013年

68

cut次のコマンドを使用できます。

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

プリント

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

インクルード

  • -d' '-つまり、space区切り文字として使用します
  • -f3,5 -3列目と5列目を取得して印刷します

cutあるはるかに高速純粋なシェル溶液のような大きなファイルのために。ファイルが複数の空白で区切られている場合は、次のように最初に空白を削除できます。

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

ここで、(gnu)sedは、任意の文字tabまたはspace文字を単一のspace。に置き換えます。

バリアントの場合-これもperlソリューションです:

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

1
うまく機能します...各行のスペースの数が正確に保証されている場合... :)
rogerdpack 2018年

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

素晴らしく、読みやすく、perls / awks / otherは必要ありません。すべて、組み込みの1つのシェルに収められています。
PetrMatousu19年

6

もう1つの単純なバリアント-

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

4

ファイルにn行が含まれている場合、スクリプトはファイルをn回読み取る必要があります。したがって、ファイルの長さを2倍にすると、スクリプトが実行する作業量が4倍になります。必要なのは行を順番にループするだけなので、その作業のほとんどすべてが単純に破棄されます。

代わりに、ファイルの行をループする最良の方法はwhile、condition-commandが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、Tom van der Woerdtが示唆するように、または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 ; 
...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.