我想知道是否有一种简单的方法可以使用预先分配的行号对某些行进行操作。
假设我想输出文件的第 1、7、14 和 16 行,我可以简单地执行
sed -n '1p;7p;14p;16p' input_file
但是当操作不仅仅是打印时,这会变得更加复杂,并且我不想将相同的长命令写入 4 次(是的,我知道我可以通过替换相同的 bash 变量 4 次来构造这个长 sed 命令,但是这还不够理想......),即
sed -n '1{long_command};7{long_command};14{long_command};16{long_command}' input_file
有没有办法对我的文件的这些特定行进行操作?我期待类似的事情,
sed -n '1,7,14,16p'
这在当前的形式下肯定行不通。
任何帮助将不胜感激。 “不,这不可能。”带解释也是我会接受的答案。
答案1
您可以使用分支:
sed '
1b1
7b1
14b1
16b1
# for the rest to be left alone, branch off (or delete them with "d"):
b
:1
long_command'
(请注意,您还可以添加一些20,25b1
行范围,或/re/b1
包含与 匹配的行re
)。
或者你可以使用awk
:
awk 'NR == 1 || NR == 7 || ... {stuff}'
或者使用哈希:
awk -v l=1,7,14,16 '
BEGIN{split(l, a, ","); for (i in a) lines[a[i]]}
NR in lines {stuff}'
(或者BEGIN{lines[1]lines[7]lines[14]lines[16]}
如果没有太多的话)
答案2
只需反转您的选择并将其删除:
sed '2,6d;8,13d;15d;17,$d;long_command'
答案3
第一个变体:
你可以使用这个技巧:
sed -nf <(printf '%dp\n' 1 7 14 16)
-F 脚本文件- 将脚本文件的内容添加到要执行的命令中。
测试
seq 1 20 | sed -nf <(printf '%dp\n' 1 7 14 16)
输出
1
7
14
16
第二种变体:
一开始,辅助文件sed
用于仅过滤文件中需要的行,然后sed
使用长命令将这些行通过管道传送到主文件。
sed -n '1p; 7p; 14p; 16p' input.txt | sed 'long command'