07、sed 条件判断

判断语句要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)

sed语言也有条件判断,不过它的条件判断语法真的有点反人类,为什么呢 ?

sed语言的条件判断没有 if 语句,没有 switch 语句,而是一个简单的 b 命令

字符b 是 break 的缩写。

sed 标签语法

sed也有标签 ( label ) 这个概念,而且可以设置标签。

sed的条件判断,就是当条件满足时跳转到的标签标记的行并继续执行其余命令来实现的。

sed语言使用 冒号(:) 来实现标签名。

sed中设置 标签 ( label ) 的语法如下:

:label 
:start 
:end 
:up

定义了标签之后,如果要跳转到某个标签名,可以使用 b 命令。

b命令的语法格式为

b[label_name]

其中[label_name] 为要跳转到的标签名。这是一个可选项,如果忽略,那么 sed 会跳转到 sed 命令文件的末尾,也就是结束所有 sed 命令。

看到这种语法是不是很想打人,奇怪又难记。

sed 条件判断

sed语言的条件判断的流程为:

1、 先使用标签语法:<label>定义一个标签label;
2、 然后使用**<condition>b<label>**命令判断一个条件condition的真假,如果为真则跳转到刚刚定义的标签label处,为假则继续往下执行语句;

因此,一个简单的 sed 条件判断语句的语法格式如下

/<pattern/b label

当然了,sed 也支持对条件取反,也就是 条件为假时跳转到指定标签处,这时候就需要使用逻辑非运算符 !,语法格式如下

/<pattern/!b label

这个语法,是不是有点难记又难懂? 简直不是人类可理解的嘛

范例

看了有点复杂啊,我们来写一个范例吧。不过呢,看了范例感觉更复杂...五味杂陈

我们下来看看我们要处理的数据文件,是当前目录下的一个叫 data.txt 的文件,内容如下

I am 
studing sed
I am 
www.ddkk.com
I am 
a no-work-men
I am 
so handsome

就是一些 我是... 的语句。

这时候,我真想说,我是傻逼,竟然学这么复杂的 sed 语言。

下面的代码首先把相邻的两行组合在一起,也就是把第一行和第二行组合在一起,第二行和第三行组合在一起...。

然后把行中的换行符(\n)替换为 冒号(:) 。接着查找行中是否有 ddkk 字符串,如果有的话在行的开头追加 - 。如果没有则直接跳转到 Print 标签处直接输出。

[www.ddkk.com]$ sed -n ' 
h;n;H;x 
s/\n/: / 
/ddkk/!b Print 
s/^/- / 
:Print 
p' data.txt

运行上面的 sed 程序,输出结果如下

I am : studing sed
- I am : www.ddkk.com
I am : a no-work-men
I am : so handsome

看到上面代码的第一眼,我怎么觉得所有字母都认识,但是放到一起就不认识了呢

  • 第一行 h;n;H;x 语句用于把相邻的两行放到一起

  • h 命令拷贝模板块的内容到内存中的缓冲区

  • n 命令读取下一个输入行,用下一个命令处理新的行而不是第一个命令

  • H 命令追加模板块的内容到内存中的缓冲区

  • x 命令表示互换模板块中的文本和缓冲区中的文本

  • 第二行 s/\n/, / 把模板块的文本中的 换行符(\n) 替换成 :。

  • 第三个命令是一个 模式匹配 语句,如果没找到 ddkk 则跳转到标签 Print,如果找到则由第四个命令执行替换操作。

  • 第四个命令是在行的开头插入 - 。这是一个正则表达式,意思是查找开头并把开头替换为 -

  • :Print 是一个名为 Print 的标签,而 p 命令,想必你是知道的,是 输出命令

上面的sed 程序,为了方便阅读,我们把每一个 sed 命令都放在了单独的一样。其实更多时候,我们会把它们放到一行上,多条 sed 命令之间使用 分号(;) 分隔。

就像下面这样

[www.ddkk.com]$ sed -n 'h;n;H;x;s/\n/: /;/ddkk/!b Print; s/^/- /; :Print;p' data.txt

运行上面的 sed 程序,输出结果如下

I am : studing sed
- I am : www.ddkk.com
I am : a no-work-men
I am : so handsome