使用 head 和 tail 抓取不同的行集并保存到同一个文件中

use*_*291 11 tail head

所以这是家庭作业,但我不会问具体的家庭作业问题。

我需要使用 head 和 tail 从一个文件中获取不同的行集。所以像第 6-11 行和第 19-24 行一样,将它们都保存到另一个文件中。我知道我可以使用 append 来做到这一点,例如

head -11 file|tail -6 > file1; head -24 file| tail -6 >> file1. 
Run Code Online (Sandbox Code Playgroud)

但我认为我们不应该这样做。
有没有一种特定的方法可以组合 head 和 tail 命令然后保存到文件中?

don*_*sti 13

head如果您{ ... ; }使用类似的构造对命令进行分组,则可以使用单独的基本算术来完成

{ head -n ...; head -n ...; ...; } < input_file > output_file
Run Code Online (Sandbox Code Playgroud)

其中所有命令共享相同的输入(感谢@mikeserv)。
获取第 6-11 行和第 19-24 行等效于:

head -n 5 >/dev/null  # dump the first 5 lines to `/dev/null` then
head -n 6             # print the next 6 lines (i.e. from 6 to 11) then
head -n 7 >/dev/null  # dump the next 7 lines to `/dev/null` ( from 12 to 18)
head -n 6             # then print the next 6 lines (19 up to 24)
Run Code Online (Sandbox Code Playgroud)

所以,基本上,你会运行:

{ head -n 5 >/dev/null; head -n 6; head -n 7 >/dev/null; head -n 6; } < input_file > output_file
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 7

您可以使用{ … }分组构造将重定向运算符应用于复合命令。

{ head -n 11 file | tail -n 6; head -n 24 file | tail -n 6; } >file1
Run Code Online (Sandbox Code Playgroud)

您可以跳过前 M 行并复制下 N 行,而不是复制前 M+N 行并仅保留最后 N 行。这在大文件上明显更快。请注意,+Nof的参数tail不是要跳过的行数,而是加一 - 它是从 1 开始打印的第一行的编号。

{ tail -n +6 file | head -n 6; tail -n +19 file | head -n 6; } >file1
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,输出文件只打开一次,但输入文件被遍历一次以提取每个片段。如何对输入进行分组?

{ tail -n +6 | head -n 6; tail -n +14 | head -n 6; } <file >file1
Run Code Online (Sandbox Code Playgroud)

一般来说,这是行不通的。(它可能适用于某些系统,至少当输入是常规文件时。)为什么?由于输入缓冲。大多数程序,包括tail,不会逐字节读取输入,而是一次读取几千字节,因为它更快。所以tail读取几千字节,在开始时跳过一点,再传递一点到head,然后停止——但是读取的内容是读取的,不能用于下一个命令。

另一种方法是使用headpiped /dev/nullto 跳过行。

{ head -n 5 >/dev/null; head -n 6; head -n 7 >/dev/null; head -n 6; } <file >file1
Run Code Online (Sandbox Code Playgroud)

同样,由于缓冲,这不能保证工作。head当输入来自常规文件时,它恰好与来自 GNU coreutils的命令(在非嵌入式 Linux 系统上找到的那个)一起使用。这是因为一旦这个实现head读取了它想要的内容,它就会将文件位置设置为它没有输出的第一个字节。如果输入是管道,这将不起作用。

从文件中打印多个行序列的更简单方法是调用更通用的工具,例如sedawk。(这可能会更慢,但它只对非常大的文件很重要。)

sed -n -e '6,11p' -e '19,24p' <file >file1
sed -e '1,5d' -e '12,18d' -e '24q' <file >file1
awk '6<=NR && NR<=11 || 19<=NR && NR<=24' <file >file1
awk 'NR==6, NR==11; NR==19, NR==24' <file >file1
Run Code Online (Sandbox Code Playgroud)

  • 它不会*碰巧工作,*它是标准的、指定的行为——当然,正如你所说,管道*不是*共享输入的可靠输入源。[实用程序描述默认值](http://pubs.opengroup.org/onlinepubs/7908799/xcu/utildes.html):*当标准实用程序读取可查找的输入文件并在到达文件末尾之前没有错误地终止时,该实用程序将确保打开文件描述中的文件偏移正确定位在该实用程序处理的最后一个字节之后。* (2认同)