sed 范围并不总是只能匹配一行

x-y*_*uri 6 shell sed

考虑以下范围:1,/pattern/. 如果模式在第一行匹配,则整个文件的范围匹配:

$ cat 1.sh
#!/usr/bin/env bash
set -eu
seq 1 4 | sed -rn '1,/'"$1"'/p'
$ ./1.sh 1
1
2
3
4
$ ./1.sh 2
1
2
Run Code Online (Sandbox Code Playgroud)

你会怎么做?

UPD这是我所做的(以防万一):

re='/1/'
seq 1 4 | sed -rn "1{$re{p;q}}; 1,${re}p"
Run Code Online (Sandbox Code Playgroud)

或者这样:

seq 1 4 | sed -rn "1{/1/{p;q}}; 1,//p"
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 6

是的,这是一件令人讨厌的事情sed(请参阅有关该sed问题的常见问题解答)。由于您使用的是 GNU sed-r特定于 GNU),您可以执行以下操作:

 sed -En "0,/$1/p"
Run Code Online (Sandbox Code Playgroud)

(我更喜欢它-E-r因为它也受其他一些工具的支持,sed例如 FreeBSD,并且与grep其他一些工具一致(并且将在下一期的 POSIX/Single UNIX 规范标准中介绍))。

一个更好的选择(和便携)是:

sed "/$1/q"
Run Code Online (Sandbox Code Playgroud)

sed在第一场比赛后告诉退出(并停止阅读)。

请注意,awk没有问题,因此您可以编写:

PATTERN=$1 awk 'NR==1, $0 ~ ENVIRON["PATTERN"]'
Run Code Online (Sandbox Code Playgroud)

(虽然像 for sed,你宁愿写):

PATTERN=$1 awk '1; $0 ~ ENVIRON["PATTERN"] {exit}'
Run Code Online (Sandbox Code Playgroud)

  • @x-yuri,是的,它曾经用于 BSD 的可移植性,但没有记录。请注意,[-E 正在进入 POSIX](http://austingroupbugs.net/view.php?id=528),所以 GNU `sed` [正在记录它](http://git.savannah. gnu.org/cgit/sed.git/commit/?id=8b65e07904384b529a464c89f3739d2e7e4d5135)。我想知道是什么让 GNU sed 作者首先想到了选择 `-r`。 (2认同)