web-dev-qa-db-ja.com

多くのファイルの最後から2番目の行を1つのファイルに印刷するにはどうすればよいですか?

1つのディレクトリにさまざまな長さのCSVファイルがたくさんあります。各ファイルの最後から2番目の行を1つのファイルに入れたいのですが。 tail -2 * | head -1 > file.txtのようなものを試したところ、なぜそれが機能しないのかがわかりました。

BusyBoxv1.19.4を使用しています。

編集:他のいくつかの質問との類似性はわかりますが、これは複数のファイルの読み取りに関するものであるため異なります。 TomHuntの答えのforループは、私が必要としていて、以前は考えていなかったものです。

1
aswine
for i in *; do tail -2 "$i" | head -1; done >>file.txt

これはsh(したがってBusybox)と互換性があるはずですが、ATMのテストに使用できる非bashはありません。

有益なコメントに従って編集。

8
Tom Hunt

GNUまたはBSDsedの場合:

sed -s 'x;$!d' -- files... >outfile

...例えば:

for   i in        10 50 100 1000
do    seq "$i"   >file"$i"
done
sed -s 'x;$!d' -- file[15]0*

9
99
999
49

tailでも実行できます:

tail -n2 file[15]0* | sed -ne'n;p;n;n'

9
99
999
49

...ただし、各infileに少なくとも2行あることをsureする必要があります。その場合、sedは 'ではないためです。 t -sストリームを分離すると、1回限りの出力が残りの出力に影響します。ただし、tailは、各ファイルの最後の2行よりも多いを出力することはなく、次の各セットの後に続きます。空白行があり、指定されたファイル名ヘッダーで各セットをリードします(実際には、ファイル名に改行があると問題が発生する可能性があります)

これはtailが出力するものです:

tail -n2 file[15]0*

==> file10 <==
9
10

==> file100 <==
99
100

==> file1000 <==
999
1000

==> file50 <==
49
50

...これより良いオプションがない場合、ストリームを処理するのはそれほど難しいことではありません。

そして、それについて考えると、ファイル内にare未満の行がある場合、sedソリューションはそのファイルの空白行を出力します。必要に応じて、そのファイルには何も書き込まれません。

sed -s 'x;$!d;1d' -- file[15]0*

...トリックを行います。


tail | sedコマンドはbusyboxビルトインでのみ機能しますが、残念ながら、busybox sednotを処理します-separatestreamsオプション。少なくとも、私のビルドはそうではありません:

busybox sed --help

BusyBox v1.21.1 (2013-07-28 11:02:27 EDT) multi-call binary.

Usage: sed [-inr] [-f FILE]... [-e CMD]... [FILE]...
or: sed [-inr] CMD [FILE]...

また、イライラすることに、 toybox sed(これは私が非常に好み、Androidシステム)は、--help出力のオプションをサポートしていると誤って報告し、他の場所での認識を拒否します。

toybox sed -s -e 'x;$!d' -- file[15]0*

usage: sed [-inrE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]

Stream editor. Apply one or more editing SCRIPTs to each line of input
(from FILE or stdin) producing output (by default to stdout).

-e  add SCRIPT to list
-f  add contents of SCRIPT_FILE to list
-i  Edit each file in place.
-n  No default output. (Use the p command to output matched lines.)
-r  Use extended regular expression syntax.
-E  Alias for -r.
-s  Treat input files separately (implied by -i)

...

sed: Unknown option s

くそー。

4
mikeserv