次のような複数のファイルがあります:(実際には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
while
ループを削除し、シェルブレース展開と組み込みFNR
変数awk
を利用します。
awk 'FNR==2{print $0 > "output.dat"}' file{1..80}.dat
sed
で十分です:
sed -sn 2p file{1..80}.dat > output.dat
各ファイルの2行目を印刷するには、-s
オプションが必要です。それ以外の場合は、最初のファイルの2行目のみが印刷されます。
...head -n 2 input.dat | tail -n 1 | awk
...
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
これを行うには明らかにたくさんの方法があります-私は好きだと思います @ aragaerのsed回答 。
純粋なbashビルトインを使用し、外部ユーティリティをフォークする必要がないものを次に示します。
for f in file{1..80}.dat; do
{ read && read && printf "%s\n" "$REPLY"; } < "$f"
done > output.dat
ここで複数のファイルに対する回答で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