ChatGPT解决这个技术问题 Extra ChatGPT

获取第 n 行 STDOUT 的命令

是否有任何 bash 命令可以让您获得 STDOUT 的第 n 行?

也就是说,会采取这种

$ ls -l
-rw-r--r--@ 1 root  wheel my.txt
-rw-r--r--@ 1 root  wheel files.txt
-rw-r--r--@ 1 root  wheel here.txt

并做类似的事情

$ ls -l | magic-command 2
-rw-r--r--@ 1 root  wheel files.txt

我意识到在编写要重用的脚本时这是一种不好的做法,但是在日常使用 shell 时,能够以这种方式过滤我的 STDOUT 对我很有用。

我也意识到这将是一个简单的命令(缓冲 STDOUT,返回特定的行),但我想知道是否有一些标准的 shell 命令可以执行此操作,而无需我将脚本放置到位。

我刚刚投票赞成使用magic-command这个词

J
Jonathan Leffler

使用 sed,只是为了多样化:

ls -l | sed -n 2p

使用这种看起来更有效的替代方法,因为它在打印所需的行时停止读取输入,可能会在馈送过程中生成 SIGPIPE,这反过来可能会生成不需要的错误消息:

ls -l | sed -n -e '2{p;q}'

我经常看到我通常使用第一个(无论如何更容易键入),尽管 ls 不是一个在获得 SIGPIPE 时会抱怨的命令。

对于一系列行:

ls -l | sed -n 2,4p

对于几个范围的行:

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'

p 是什么意思?像2p 3p?从某种意义上说,我理解它适用于 2/3 线,但它背后的理论/理解是什么?
@LeoUfimtsev: psed 语句,它打印由其前面的行范围标识的行。因此 2,4p 表示打印第 2、3、4 行。
n 表示不打印所有其他行
m
mob
ls -l | head -2 | tail -1

+2,但我建议head -n 2 | tail -n 1——现代的正面和反面往往会发出警告。
使用两个进程来过滤数据有点矫枉过正(但是,鉴于当今机器的强大功能,它们可能会应付)。泛化以处理一个范围并非完全微不足道(对于范围 N..M,您使用 head -n M | tail -n M-N+1),并且无法泛化以处理多个范围。
头管成尾巴?可怕。多种更好的方法来做到这一点。
*nix 命令行的伟大之处:一百万零一种做所有事情的方法,每个人都有一个最喜欢和一个讨厌所有其他方式...... :-)
如何以另一种方式打印一系列行:$ ls -l | awk '{if (NR>=4 && NR<=64) print}'(可以更轻松地添加更多条件,多个范围等......)
M
Mark Edgar

替代漂亮的头/尾方式:

ls -al | awk 'NR==2'

或者

ls -al | sed -n '2p'

我的 awk 更好,但 sed 很好。
不需要“如果” - 请参阅黑客的答案(关于查找系统上每个文件的部分除外)。 ;-)
'2p' 代表什么?
@shredding 简答打印第二行;长->使用时,只有与模式匹配的行才会在地址后给出命令。简而言之,当与 /p 标志一起使用时,匹配的行会打印两次:sed '/PATTERN/p' 文件。当然 PATTERN 是任何正则表达式 more
如果 2 是一个变量怎么办?每个示例都使用单引号,但对于 var,您需要双引号。使用 var 时,我们可以“编程”awk 以使用单引号吗?示例 line =1; ls | awk 'NR==$line'。我知道 bash 使用带变量的双引号。
M
Mark Edgar

sed1line

# print line number 52
sed -n '52p'                 # method 1
sed '52!d'                   # method 2
sed '52q;d'                  # method 3, efficient on large files

awk1line

# print line number 52
awk 'NR==52'
awk 'NR==52 {print;exit}'          # more efficient on large files

Z
Zombo

为了完整起见;-)

更短的代码

find / | awk NR==3

寿命短

find / | awk 'NR==3 {print $0; exit}'

你不是在开玩笑完整性!
我不是 ;-) 实际上,我不知道为什么每个人都在使用 ls — 最初的问题是关于某人的 STDOUT,所以我认为最好让它更大。
至少对于 GNU awk,默认操作是 { print $0 },所以 `awk 'NR==3' 是一种更短的写法。
您可能应该在该操作中添加“; exit”。当你不打算对它们做任何事情时,处理其余的行是没有意义的。
@camh:请参阅 Jonathan Leffer 对此的回答:“可能会在馈送过程中生成 SIGPIPE,这反过来可能会生成不需要的错误消息”。
D
Dennis Williamson

试试这个 sed 版本:

ls -l | sed '2 ! d'

它说“删除所有不是第二行的行”。


H
Hai Vu

您可以使用 awk:

ls -l | awk 'NR==2'

更新

上面的代码不会得到我们想要的,因为一个错误: ls -l 命令的第一行是总行。为此,以下修改后的代码将起作用:

ls -l | awk 'NR==3'

c
catfood

Perl 对你来说很容易使用吗?

$ perl -n -e 'if ($. == 7) { print; exit(0); }'

显然用你想要的任何数字代替 7。


这是我最喜欢的,因为它似乎是最容易概括为我个人之后的每 n 次, perl -n -e 'if ($. %7==0) { print;退出(0); }'
@matkelcey 您也可以执行 $ awk 'NR % 7' filename 来打印文件中的每 7 行。
n
nobody

另一张海报建议

ls -l | head -2 | tail -1

但是,如果您将头插入尾,则看起来直到第 N 行的所有内容都被处理了两次。

将尾巴插入头部

ls -l | tail -n +2 | head -n1

会更有效率吗?


佚名

是的,最有效的方法(正如 Jonathan Leffler 已经指出的那样)是将 sed 与 print & quit 一起使用:

set -o pipefail                        # cf. help set
time -p ls -l | sed -n -e '2{p;q;}'    # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}"            # cf. man bash | less -p 'PIPESTATUS'

pipefail 和 PIPESTATUS 的使用非常有趣,这给这个页面增加了很多。
s
stan

sed 在我的情况下不起作用。我提议:

对于“奇数”行 1,3,5,7... ls |awk '0 == (NR+1) % 2' 对于“偶数”行 2,4,6,8 ls |awk '0 == ( NR) % 2'


S
Shizzmo

为了更完整..

ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)

丢弃行,直到到达第二行,然后打印出第一行。所以,它打印第三行。

如果只是第二行..

ls -l | (read; head -n1)

根据需要放置尽可能多的“阅读”。