如何从cat输出中读取第一行和最后一行?


64

我有文本文件。任务-从文件之后获取第一行和最后一行

$ cat file | grep -E "1|2|3|4" | commandtoprint

$ cat file
1
2
3
4
5

需要没有cat输出(仅1和5)的此功能。

~$ cat file | tee >(head -n 1) >(wc -l)
1
2
3
4
5
5
1

也许awk和更短的解决方案存在...


在第二个示例中,wc -l与输出文件的最后一行无关。
David Richerby 2014年

Answers:


115

sed解决方案:

sed -e 1b -e '$!d' file

stdinif 读取时将如下所示(例如ps -ef):

ps -ef | sed -e 1b -e '$!d'
UID        PID  PPID  C STIME TTY          TIME CMD
root      1931  1837  0 20:05 pts/0    00:00:00 sed -e 1b -e $!d

头尾解决方案:

(head -n1 && tail -n1) <file

当数据来自命令(ps -ef)时:

ps -ef 2>&1 | (head -n1 && tail -n1)
UID        PID  PPID  C STIME TTY          TIME CMD
root      2068  1837  0 20:13 pts/0    00:00:00 -bash

awk解决方案:

awk 'NR==1; END{print}' file

还有管道的示例ps -ef

ps -ef | awk 'NR==1; END{print}'
UID        PID  PPID  C STIME TTY          TIME CMD
root      1935  1837  0 20:07 pts/0    00:00:00 awk NR==1; END{print}

1
谢谢!这是最好的答案,因为我做不了(head -n1 file;tail -n1 file)很大的命令和管道作为最后一个符号。这么| sed '1p;$!d'短。
dmgl 2014年

抱歉,如果您对我的英语不了解-这是我的问题-请告诉我,我会为您准备更好的演示文稿。
dmgl 2014年

7
难道head && tail你真的有用吗?仅seq 10 | (head -n1 && tail -n1)打印1
glenn jackman 2014年

1
@DavidConrad,要详细说明混乱的内容,-e 1b在第一行上,分支到sed脚本的末尾,这时将发生隐式“打印”。如果输入只有一行,则sed结束。否则,对于除最后一行以外的所有行,请删除。在最后一行,隐式的“打印”再次发生。
glenn jackman 2014年

1
@mikeserv:;-)有机会时检查一下。在单行上,它有效地防止了其在输出上加倍,但是在多行工作用例中,它仅保留了最后一行……至少在GNU sed4.2.2上。干杯。
Cbhihe

23

sed -n '1p;$p' file.txt 将打印file.txt的第一行和最后一行。


10
请注意,如果输入只有一行,它将被打印两次。sed -e 1b -e '$!d'如果您不希望这样做,则可能会更喜欢。
斯特凡Chazelas

10

一个有趣的纯Bash≥4方式:

cb() { (($1-1>0)) && unset "ary[$1-1]"; }
mapfile -t -C cb -c 1 ary < file

之后,您将得到一个数组,ary其中第一个字段(即index 0)为的第一行file,而其最后一个字段为的最后一行file。回调cb(如果要对数组中的所有行都加注,则为可选)会取消所有中间行的设置,以免使内存混乱。作为免费的副产品,您还将在文件中拥有行数(作为array + 1的最后一个索引)。

演示:

$ mapfile -t -C cb -c 1 ary < <(printf '%s\n' {a..z})
$ declare -p ary
declare -a ary='([0]="a" [25]="z")'
$ # With only one line
$ mapfile -t -C cb -c 1 ary < <(printf '%s\n' "only one line")
$ declare -p ary
declare -a ary='([0]="only one line")'
$ # With an empty file
$ mapfile -t -C cb -c 1 ary < <(:)
declare -a ary='()'

7

有了sed你可以delete行,如果1ST一个AND NOT洛杉矶$t的一。
使用!NOT(否定)的条件和X{Y..}结构结合X Y条件:

cmd | sed '1!{$!d;}'

或者您可以使用范围-从2nd到lat- $并删除该范围内除lat $行之外的所有行:

cmd | sed '2,${$!d;}'

6

使用Perl:

$ seq 10 |  perl -ne 'print if 1..1 or eof'
1
10

上述在打印的输出中的第一项seq 10通过if 1..1,同时or eof也将打印的最后一个项目。


3
您能解释一下这是如何工作的吗?请避免在不解释其作用和方式的情况下给出此类一线回答。
terdon

1
什么/etc abrtyum.repos.d必须做的这个问题?
2014年

@drs我编辑了答案,以避免使用“ ls”作为示例输入。
dolmen 2014年

1
@dolmen:通过取消所有对/ etc的引用来完成编辑可能是一个好主意。我想这是在您第一次编辑后添加的,但是同样如此,因为答案是毫无意义的。只是一个建议。
Cbhihe

4

没有猫:

$ cat file |tee >(head -n1) >(tail -n1) >/dev/null
1
5

要么

$ (head -n1 file;tail -n1 file)
1
5

8
在第一个中,不保证行的顺序。
斯特凡Chazelas

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.