sed
的API是原始的-这是设计使然。至少,它在设计上仍然是原始的-我不能说它是否一开始就是原始设计的。在大多数情况下,编写一个sed
脚本,该脚本在运行时将输出另一个sed
脚本,这确实很简单。sed
通常由宏预处理器(例如m4
和/或)以这种方式应用make
。
(下面是一个高度假设的用例:这是一个设计成适合解决方案的问题。如果您觉得这很麻烦,那可能是因为确实如此,但这并不一定会使它的有效性降低。)
考虑以下输入文件:
cat <<"" >./infile
camel
cat dog camel
dog cat
switch
upper
lower
如果我们想编写一个sed
脚本,仅在可以在适当上下文中的一行上找到该单词的情况下,才将单词-case附加到上述输入文件中每个相应单词的尾部,我们希望尽可能高效地做到这一点(就像我们的目标(例如在编译操作期间)一样,那么我们应该宁愿避免尽可能多地使用regexp 。/
/
我们可能要做的一件事就是立即在我们的系统上预编辑文件,而sed
在编译过程中完全不要调用。但是,如果应该基于本地设置和/或编译时选项在文件中包含或不包含这些单词中的任何一个,则这样做可能不是理想的选择。
我们可能要做的另一件事是现在针对正则表达式处理文件。我们可以生成一个sed
脚本并将其包含在我们的编辑中,该脚本可以根据行号进行编辑-从长远来看,这通常是一种效率更高的途径。
例如:
n=$(printf '\\\n\t')
grep -En 'camel|upper|lower' <infile |
sed " 1i${n%?}#!/usr/heirloom/bin/posix2001/sed -nf
s/[^:]*/:&$n&!n;&!b&$n&/;s/://2;\$a${n%?}q"'
s/ *cat/!/g;s/ *dog/!/g
s| *\([cul][^ ]*\).*|s/.*/\1-case/p|'
...以sed
脚本形式编写输出,看起来像...
#!/usr/heirloom/bin/posix2001/sed -nf
:1
1!n;1!b1
1s/.*/camel-case/p
:2
2!n;2!b2
2!!s/.*/camel-case/p
:5
5!n;5!b5
5s/.*/upper-case/p
:6
6!n;6!b6
6s/.*/lower-case/p
q
当该输出保存到我的机器上的可执行文本文件中,该文件名为./bang.sed
并运行为时./bang.sed ./infile
,输出为:
camel-case
upper-case
lower-case
现在您可能会问我...我为什么要这样做?为什么我不只是锚定grep
比赛?谁使用骆驼套?我只能回答每个问题,我不知道...因为我不知道。在阅读此问题之前,我从未亲自注意到多!规范中的解析要求-我认为这很不错。
的多!不过,对我而言,事情确实变得很有意义-很多sed
规范都针对简单地解析和简单生成的 sed
脚本。您可能会发现所需的\n
ewline分隔符,[wr:bt{]
以便在这种情况下更有意义,并且如果牢记这一点,则可能会更好地理解规范的其他方面(例如,不:
接受地址,并q
拒绝接受不超过1个)。
在上面的例子中我写了某种形式的sed
脚本,只能永远被读取一次。如果您认真研究它,您可能会注意到,在sed
读取编辑文件时,它会从一个命令块前进到下一个命令块-它永远不会脱离或完成其编辑脚本,直到完全通过其编辑文件为止。
我认为那多!在这种情况下,地址可能比在其他情况下更有用,但是老实说,我想不出一个可以很好地利用它的情况-我sed
很多。我也认为值得一提的是,GNU / BSD sed
都无法按指定的方式处理它-这可能不是规范中要求很高的一个方面,因此,如果实现忽略了它,我非常怀疑他们的bugs @ box是否会遭受损失结果非常可怕。
就是说,未能按规定处理此问题对于任何伪装成合规性的实现都是一个错误,因此,我认为在这里需要向相关开发人员发送电子邮件,如果您不这样做,我打算这样做。
!
它用作切换按钮,/pattern/!!
与相同/pattern/
,并且/pattern/!!!
与相同/pattern/!
。在FreeBSD上,多个!
与单个相同。