如何将多个文件的倒数第二行打印到一个文件中?

如何将多个文件的倒数第二行打印到一个文件中?

我在一个目录中有许多长度各异的 CSV 文件。我想将每个文件的倒数第二行放入一个文件中。我尝试了类似的方法tail -2 * | head -1 > file.txt,然后意识到为什么这不起作用。

我正在使用 BusyBox v1.19.4。

编辑:我确实看到与其他一些问题的相似之处,但这是不同的,因为它是关于读取多个文件。汤姆亨特的答案中的循环for是我需要的,但之前没有想到。

答案1

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

这应该是sh(因此 Busybox)兼容的,但我没有可用于测试 ATM 的非 bash。

根据有用的评论进行编辑。

答案2

使用 GNU 或 BSD sed

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

...但你需要当然每个内文件中至少有两行,因为在这种情况下sed不会-s分离任何流,并且一次性将影响输出的其余部分。但tail绝对不会打印任何更多的比每个文件中的最后两行要多,并且它将在每组后面加上一个空行,并用其规范的文件名标头引导每组(实际上,如果文件名中有换行符,这可能会导致问题)

这是tail打印的内容:

tail -n2 file[15]0*

==> file10 <==
9
10

==> file100 <==
99
100

==> file1000 <==
999
1000

==> file50 <==
49
50

...如果您没有更好的选择,那么处理流并不是那么困难。

并想一想,如果有的话文件中少于两行,sed解决方案将为该文件输出一个空行。如果您希望它不为该文件写入任何内容:

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

...就可以了。


tail | sed命令仅适用于busybox内置命令,但不幸的是,busybox sed它确实不是处理-s分离流选项。至少,我的构建没有:

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

该死。

相关内容