web-dev-qa-db-ja.com

awk-複数の.datファイルの2行目を1つのファイルに出力する

次のような複数のファイルがあります:(実際には80あります)

file1.dat

2 5

6 9

7 1

file2.dat

3 7

8 4

1 3

最終的に、2行目がすべて含まれているファイルが必要になります。つまり.

output.dat

6 9

8 4

これまでのところ、ファイル名をループしますが、その前にファイルを上書きします。例えば上記のファイルの出力は単に

8 4

私のシェルスクリプトは次のようになります。

post.sh

TEND = 80

TINDX = 0

while [ $TINDX - lt $TEND]; do

awk '{ print NR==2 "input-$TINDX.dat > output.dat

TINDX = $((TINDX+1))

done
9
Rowland

whileループを削除し、シェルブレース展開と組み込みFNR変数awkを利用します。

awk 'FNR==2{print $0 > "output.dat"}' file{1..80}.dat
17
jimmij

sedで十分です:

sed -sn 2p file{1..80}.dat > output.dat

各ファイルの2行目を印刷するには、-sオプションが必要です。それ以外の場合は、最初のファイルの2行目のみが印刷されます。

7
aragaer

...head -n 2 input.dat | tail -n 1 | awk ...

6
HarveyP

aragaerのsedソリューションは最高です。しかし、私はhead|tailを少し楽しんでいるので、単一のhead|tailではなく、複数のファイルをサポートするinput.datソリューションを用意しています。 sedにファイルのリストを渡す代わりにforループを使用すると、sedで2行目を抽出する前/後にファイルで他のことを簡単に実行できます。

# empty output.dat first
rm output.dat

# have a one-liner
for file in *.dat; do head -2 $file | tail -1 >> output.dat; done 

たくさんコメントされた複数行バージョン:

注意:以下のコードが実行されます。 |&&、または||の後に改行を入れて、次の行にコマンドを続けることができます。間にコメントを入れることもできます。私はこれを知らずに過ごしました(そして、実際にはどこにもそれを見ませんでした)。このスタイルは、対話型プロンプトではあまり役に立ちませんが、スクリプトファイルをクリーンアップします。

# empty output.dat first
rm output.dat

for file in *.dat; do
    # file -> lines 1 and 2 of file
    head -2 $file |
    # lines 1 and 2 of file -> line 2 of file >> appended to output.dat
    tail -1 >> output.dat
done
2
Esteis

これを行うには明らかにたくさんの方法があります-私は好きだと思います @ aragaerのsed回答

純粋なbashビルトインを使用し、外部ユーティリティをフォークする必要がないものを次に示します。

for f in file{1..80}.dat; do
    { read && read && printf "%s\n" "$REPLY"; } < "$f"
done > output.dat
0
Digital Trauma

ここで複数のファイルに対する回答でawkおよびsedを効率的に使用するには、nextfileステートメントを使用してawkの不要な行の処理をスキップすることをお勧めします。

awk 'FNR==2{ print >"output.dat"; nextfile}' infile{1..80}.dat

sedを使用すると、3での処理時に終了できますrd 行とsedは次のファイルを処理します。

sed -sn '2p;3q' infile{1..80}.dat > output.dat
0
αғsнιη