如何获得“尾巴”和“头部”的逆行为?


55

有没有一种方法来获取head/ tail获取文档并获得反向输出;因为您不知道文档中有多少行?

即,我只想获取除头2行之外的所有内容foo.txt以附加到另一个文档。

Answers:


57

您可以使用它来去除两行:

tail -n +3 foo.txt

这将去除最后两行:

head -n -2 foo.txt

(假设文件以后者结尾\n


就像为标准的使用tailhead这些操作不是破坏性的。使用>out.txt,如果你想将输出重定向到一些新的文件:

tail -n +3 foo.txt >out.txt

如果out.txt已经存在,它将覆盖此文件。如果您不希望将输出附加到,请使用>>out.txt代替。>out.txtout.txt


3
re “ head,当文件以\n结尾“时。它对所有负整数都有效,除了-n -0根本不返回任何东西-n 0(使用:head(GNU coreutils)7.4)...但是,当出现尾随时\n-n -0会打印如预期的那样-,即。它会打印整个文件...因此它适用于所有非零的负值..但是-0在没有尾\n
随时会

@fred:确实很奇怪……(此处与8.12相同)。
斯蒂芬·吉梅内斯

此操作是否具有破坏性?正如我想要将文档的前两行的逆向复制到另一行一样?
chrisjlee 2011年

@Chris:不,他们只是将结果打印在通常连接到终端的“标准输出”上。我添加了一些有关如何将输出重定向到某些文件的详细信息。
斯蒂芬·吉梅内斯

7
head -n -2POSIX兼容
l0b0

9

如果只需要前N-1行,请tail用行数进行呼叫+N。(数字是您要保留的第一行的数字,从1开始,即+1表示从顶部开始,+ 2表示跳过一行,依此类推)。

tail -n +3 foo.txt >>other-document

没有简单,可移植的方式跳过最后N行。GNU head允许head -n +N作为的对应版本tail -n +N。否则,如果有tac(例如GNU或Busybox),则可以将其与tail结合使用:

tac | tail -n +3 | tac

可移植地,您可以使用awk过滤器(未经测试):

awk -vskip=2 '{
    lines[NR] = $0;
    if (NR > skip) print lines[NR-skip];
    delete lines[NR-skip];
}'

如果要从大文件中删除最后几行,可以确定要截断的片段的字节偏移,然后使用进行截断dd

total=$(wc -c < /file/to/truncate)
chop=$(tail -n 42 /file/to/truncate | wc -c)
dd if=/dev/null of=/file/to/truncate seek=1 bs="$((total-chop))"

您不能在一开始就截断文件,尽管如果您需要删除一个大文件的前几行,则可以在中移动内容


在某些系统上(例如现代Linux),您可以在一开始就截断(折叠)文件,但是通常只能截断FS块大小的倍数(因此在这种情况下实际上没有用)。
斯特凡Chazelas

3

tail手册页(即GNU tail)中:

-n, --lines=K
   output the last K lines, instead of the last 10; or use -n +K to
   output lines starting with the Kth

因此,以下应追加所有但第2行somefile.txtanotherfile.txt

tail --lines=+3 somefile.txt >> anotherfile.txt

3

要删除前n行,可以使用GNU sed。例如,如果n = 2

sed -n '1,2!p' input-file

!平均“排除此区间”。可以想象,可以获得更复杂的结果,例如

sed -n '3,5p;7p'

将显示第3、4、5、7行。使用正则表达式而不是地址可以带来更多的功能。

限制是必须预先知道行号。


1
为什么不只是sed 1,2d呢?通常越简单越好。同样,您的示例中没有任何内容是GNU Sed所特有的。您的命令全部使用Sed的标准POSIX功能
通配符,

1

您可以使用diffhead/ 的输出tail与原始文件进行比较,然后删除相同的内容,从而得到相反的结果。

diff --unchanged-group-format='' foo.txt <(head -2 foo.txt)

1

虽然tail -n +4输出文件的第4行(前3行除外)是标准且可移植的,但其head对应文件(head -n -3,除后3行以外的所有文件)却不是可移植的。

可移植地,您可以:

sed '$d' | sed '$d' | sed '$d'

要么:

sed -ne :1 -e '1,3{N;b1' -e '}' -e 'P;N;D'

(请注意,在某些系统中,sed其模式空间有限,无法缩放为的大值n)。

要么:

awk 'NR>3 {print l[NR%3]}; {l[NR%3]=$0}'

1
{   head -n2 >/dev/null
    cat  >> other_document
}   <infile

如果<infile是一个常规的lseek()-able文件,那么一定可以。上面是完全受POSIX支持的构造。


0

我的方法与Gilles类似,但是我只是使用cat反转了文件,并使用head命令将其删除。

tac -r thefile.txt | 头thisfile.txt(替换文件)


0

希望我清楚地了解您的需求。

您有几种方法可以完成请求:

tail -n$(expr $(cat /etc/passwd|wc -l) - 2) /etc/passwd

/ etc / passwd文件是文件

如果文件很大,第二种解决方案可能会有用:

my1stline=$(head -n1 /etc/passwd)
my2ndline=$(head -n2 /etc/passwd|grep -v "$my1stline")
cat /etc/passwd |grep -Ev "$my1stline|$my2ndline"

0

BSD(macOS)解决方案:

删除前两行:

tail -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

删除最后两行:

head -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

...不是很优雅,但是可以完成工作!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.