如何在输出的第二行运行不同的命令?
例如,我有echo foo | sed p
哪些输出
foo
foo
我想sed 's/foo/bar/'
在其中一个上运行以获得
bar
foo
答案1
在
$ echo foo | sed p
foo
foo
第一个foo
由命令打印p
,第二个则不打印,-n
因为sed
在循环结束时打印模式空间(就在读取下一行之前)。
foo
那么,要得到bar
,那就是:
$ echo foo | sed 'p;s/foo/bar/'
foo
bar
或者:
$ echo foo | sed -n 'p;s/foo/bar/p'
foo
bar
bar
仅当存在替换时才打印(通过替换成功时带有标志s
的命令) 。p
要获得bar
, then foo
,您需要h
旧的原始行并在打印替换结果后恢复它:
$ echo foo | sed 'h;s/foo/bar/p;g'
bar
foo
答案2
要运行不影响第一行数据的命令,您只需在子shell中运行它,并添加一个将读取并输出第一行的命令作为前缀,如下所示:
read -r line; echo "$line" # pass first line unmodified
sed 's/foo/bar/' # operate on rest of lines
所以你的整个例子看起来像这样:
$ echo foo | sed p | ( read -r line; echo "$line"; sed 's/foo/bar/')
foo
bar
答案3
最好将其传输到一个命令中,该命令可以根据输入行号执行不同的操作。
例如,与sed
:
$ printf 'foo\nfoo\n' | sed '2,$s/foo/bar/'
foo
bar
这使用 sed 的寻址语法,将操作限制s/foo/bar/
为从 2 到文件末尾 ( 2,$
) 的行。
来自man sed
(GNU 版本,稍微重新格式化以使其更具可读性):
Sed 命令可以不带地址,在这种情况下,该命令将对所有输入行执行;具有一个地址,在这种情况下,仅对与该地址匹配的输入行执行该命令;或者有两个地址,在这种情况下,将对与从第一个地址开始并继续到第二个地址的行的包含范围匹配的所有输入行执行该命令。
关于地址范围需要注意的三件事:
语法为addr1,addr2(即地址之间用逗号分隔);
即使 addr2 选择了较早的行,addr1 匹配的行也将始终被接受;
如果 addr2 是正则表达式,则不会针对 addr1 匹配的行进行测试。
或者awk
:
$ printf 'foo\nfoo\n' | awk 'NR > 1 {gsub(/foo/,"bar")};1'
foo
bar
或 Perl:
$ printf 'foo\nfoo\n' | perl -p -e 's/foo/bar/ if $. > 1'
foo
bar
awk 和 perl 版本测试行号(NR
对于 awk,$.
对于 perl)是否大于 1。