我将所有替换命令都放在一个文件(例如 replace.sed)中,并将其与 sed 的 -f 标志一起使用(sed -f replace.sed InputFile)。但现在我遇到了一种情况,我需要仅在给定输入文件的偶数行上应用这些替换规则(即仅在第 2、4、6 行等上应用)。我无法在 replace.sed 文件中放置任何条件语句,因为其他脚本也使用了该文件。
答案1
使用进程替换来sed
动态调整文件中的命令:
$ cat replace.sed
s#foo#bar#
。
$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f replace.sed
bar
bar
bar
bar
。
$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f <(sed 's#^#2~2#g' replace.sed)
foo
bar
foo
bar
答案2
sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed) InputFile
答案3
其他答案试图告诉您的是使用sed
地址形式:first~step
地址
… 支持以下地址类型:…
第一的~步匹配每一个步第行以 line 开头第一的例如,“
sed -n 1~2p
”将打印输入流中的所有奇数行,地址“2~5
”将从第二行开始匹配每五行。 第一的可以为零;在这种情况下,sed
操作就像等于 步. (这是一个扩展。)
显而易见的解决方案是将 中的每个命令放在 之前replace.sed
(2~2
或者0~2
,如果它在您的 版本中有效sed
),以使命令在每隔一行上运行,从第二行开始(即,输入流中的所有偶数行,如您所要求的)。但是你说你不能修改replace.sed
。好吧,下一步(如其他答案所确定的,但没有解释)是使用 shell 的流程替代功能,其中充当 的输出文件。如果如您的问题所暗示的那样, 只是一系列简单的替代命令,那么
<(command_list)
command_list
replace.sed
sed -f <(sed 's/^/2~2/g' replace.sed)
应该管用。
但这也有缺点:
- 如果每行有多个命令,则上述操作只会影响每行的第一个命令。
- 如果您有带有数字地址的命令(例如
42s/Zaphod/Beeblebrox/
),它们将被转换为,2~242…
结果显而易见。 - 如果您有带有非数字地址的命令(例如
/windows/s/command/cmd/
),上述操作将直接失败。
如果出现上述任何一种情况,您应使用
sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed)
将sed
每行上的所有命令放入一个命令组中。
replace.sed
但如果有多行命令,这也会失败。
基于上述想法,我想出了
sed -f <(echo '0~2{'; cat replace.sed; echo '}')
这使得全部的 replace.sed
replace.sed
文件放入命令组中。在我的初步测试中,这似乎解决了我对其他解决方案提出的问题。如果它在处理非常长的或非常复杂的命令时出现问题,我不会感到惊讶。