我遇到了一个很好的使用 tosed
做替换,并使用它的成功状态作为打印行的条件:
$ seq 3 | sed -n 's/2/B/ p'
B
我想知道是否可以扩展这种简短形式以执行更多操作。喜欢,
- 仅当替换成功时才打印该行,但是
- 在打印出来之前,我需要做更多的更换
那可能吗?我尝试了以下但失败了:
$ seq 3 | sed -n 's/2/B/ {p}'
sed: -e expression #1, char 8: unknown option to `s'
我遇到了一个很好的使用 tosed
做替换,并使用它的成功状态作为打印行的条件:
$ seq 3 | sed -n 's/2/B/ p'
B
我想知道是否可以扩展这种简短形式以执行更多操作。喜欢,
那可能吗?我尝试了以下但失败了:
$ seq 3 | sed -n 's/2/B/ {p}'
sed: -e expression #1, char 8: unknown option to `s'
您可以用作
/2/
更复杂命令的地址:对于至少包含一个的任何行
2
,这将替换第一次出现的2
withB
(在这种情况下,此替换也可以缩短为s//B/
空正则表达式表示“使用最近匹配的表达式”的位置),然后丢弃该行,如果它现在包含子字符串BB
。然后该行将被输出(如果它没有被丢弃)。其他行根本不会输出,因为-n
.你也可以使用
这将删除所有不包含的行
2
,然后应用于other commands
其余行。使用多个表达式,每个表达式都使用
-e
,是将一系列命令应用于输入流的标准方法sed
。大多数当前的sed
实现也理解用 分隔表达式;
。GNUsed
不必;
在}
.p
这是命令的标志sed
,它不是p
sed
命令。要执行某些操作(除了
p
打印生成的模式空间或w
将其写入文件,w
作为另一个可能与s
命令一起使用的标志)只有在进行了替换时,您才可以使用命令t
(或T
GNU 中的命令sed
)如果有替换(如果没有 for ),则分支到某个标签(如果没有标签,则分支到末尾-T
),所以你可以这样做:GNU 特定的:
这就像:
或者您可以使用:
在使用空正则表达式的地方,就像在
ed
.如果你需要做除此之外的任何事情,
s/old/new/
你最好使用 awk 而不是 sed 以获得清晰度、健壮性、可移植性、可维护性等的某种组合:您可以使用“{ .... }”对命令进行分组。一般形式为:
这里的“cmd”是任何常规的 sed 命令,如“s/.../.../”,还有“p”、“q”等。将此视为适用于所有的“规则”匹配正则表达式的行。您还可以通过在正则表达式和左大括号之间使用感叹号来否定规则。在这种情况下,规则适用于所有不匹配正则表达式的行。
下面是一个示例,它打印从脚本开始到第一个非注释行的所有仅注释行:
所有以“#”开头的行都匹配规则,因此只打印出来(我们没有使用“-n”选项来抑制它)。第一行(实际上是所有行,但实际上只有第一行被处理)不匹配正则表达式触发简单退出 sed 的规则。
但是还有另一种比使用规则更强大的方法:定义所谓的“标签”。使用类似于 GOTO 的命令分支到的符号位置。它是这样工作的:
1) 无条件分支 sed 脚本的工作方式如下:读取第一行输入,然后对它应用所有 sed 命令,一个接一个(如果该行被更改,则进一步的命令将应用于该更改的行)直到最后一个命令到达。如果不使用“-n”选项,结果将打印到 . 只有这样,才会读取下一行输入并重新开始该过程,直到处理完最后一行输入。
有一种方法可以更改命令应用于当前行的顺序:
这个命令本身什么都不做,但它可以被其他命令用来分支到这个地方。你可能还记得像 BASIC 这样的语言和它们的“goto”命令?这标记了一个标签,随后的“goto”-(like)-命令可以跳转到该标签。分支到先前定义的标签的无条件 sed 命令是
“b”代表“分支”。对应于您使用“:”命令定义的内容。如果省略标签,则执行分支到脚本末尾。
这是一个例子:你得到一个程序,但不幸的是代码缩进是用制表符而不是空格完成的,你想改变它。显然,您只想更改任何代码前面的选项卡,而不是代码中可能需要的选项卡。las,正则表达式中没有直接用于此的设备,因此您必须自己实现它。该算法是:只要一行的形式是空格,后面跟着一个制表符,将第一个制表符更改为 8 个空格,然后在同一行上重复,直到没有制表符位于任何文本的前面。然后才打印该行。这种类似循环的结构是使用“:”和“b”命令设置的。请注意,我在这里使用 \b(空白)和 \t(制表符)来使不同类型的空白可读。
2) 条件分支 现在,你知道如何设置标签和分支到它们还有一个更进一步的转折:你可以根据 s/.../.../ 命令在成功之前执行的分支到这样的标签(这意味着:它改变了一些东西)或没有。这样做的命令是:
如果 s/../../- 命令之一在最后一行被读取或自上次执行 at 或 T 命令后成功替换,则分支到
这是“t”的否定对应物。如果没有s-command 成功,它就会分支。
这是一个简单的例子,它是如何工作的。它没有做任何特别有用的事情,但它显示了原理:sed 脚本只接受任何输入的第一行。如果第一个字符是“a”、“b”或“c”之一,则打印“YES”,否则打印“NO”。
控制流程很简单:首先尝试替换,如果第一个字符是“a”、“b”或“c”,则将其更改为“x”。如果成功,分支命令“t yes”将分支到 lael“yes”,其中整行更改为“YES”并且 sed 退出(“q”命令)。如果此替换不成功,则传递“t”命令并执行“b”命令,跳转到“no”标签。
尝试各种输入(
echo "..." | sed <script>
足够好)以查看其工作原理,然后将“t”命令更改为“T”并观察对结果的影响。