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 语言的条件判断的流程为:
- 先使用标签语法
:<label>
定义一个标签label
。 - 然后使用
<condition>b <label>
命令判断一个条件condition
的真假,如果为真则跳转到刚刚定义的标签label
处,为假则继续往下执行语句。
因此,一个简单的 sed 条件判断语句的语法格式如下
/<pattern/b label
当然了,sed 也支持对条件取反,也就是 条件为假时跳转到指定标签处,这时候就需要使用逻辑非运算符 !
,语法格式如下
/<pattern/!b label
这个语法,是不是有点难记又难懂? 简直不是人类可理解的嘛
范例
看了有点复杂啊,我们来写一个范例吧。不过呢,看了范例感觉更复杂...五味杂陈
我们下来看看我们要处理的数据文件,是当前目录下的一个叫 data.txt
的文件,内容如下
I am studing sed I am www.twle.cn I am a no-work-men I am so handsome
就是一些 我是... 的语句。
这时候,我真想说,我是傻逼,竟然学这么复杂的 sed 语言。
下面的代码首先把相邻的两行组合在一起,也就是把第一行和第二行组合在一起,第二行和第三行组合在一起...。
然后把行中的换行符(\n
)替换为 冒号(:
)。接着查找行中是否有 twle
字符串,如果有的话在行的开头追加 -
。如果没有则直接跳转到 Print
标签处直接输出。
[www.twle.cn]$ sed -n ' h;n;H;x s/\n/: / /twle/!b Print s/^/- / :Print p' data.txt
运行上面的 sed 程序,输出结果如下
I am : studing sed - I am : www.twle.cn I am : a no-work-men I am : so handsome
看到上面代码的第一眼,我怎么觉得所有字母都认识,但是放到一起就不认识了呢
-
第一行
h;n;H;x
语句用于把相邻的两行放到一起h
命令拷贝模板块的内容到内存中的缓冲区n
命令读取下一个输入行,用下一个命令处理新的行而不是第一个命令H
命令追加模板块的内容到内存中的缓冲区x
命令表示互换模板块中的文本和缓冲区中的文本
-
第二行
s/\n/, /
把模板块的文本中的 换行符(\n
) 替换成:
。 -
第三个命令是一个 模式匹配 语句,如果没找到
twle
则跳转到标签Print
,如果找到则由第四个命令执行替换操作。 -
第四个命令是在行的开头插入
-
。这是一个正则表达式,意思是查找开头并把开头替换为-
-
:Print 是一个名为
Print
的标签,而p
命令,想必你是知道的,是 输出命令。
上面的 sed 程序,为了方便阅读,我们把每一个 sed 命令都放在了单独的一样。其实更多时候,我们会把它们放到一行上,多条 sed 命令之间使用 分号(;
) 分隔。
就像下面这样
[www.twle.cn]$ sed -n 'h;n;H;x;s/\n/: /;/twle/!b Print; s/^/- /; :Print;p' data.txt
运行上面的 sed 程序,输出结果如下
I am : studing sed - I am : www.twle.cn I am : a no-work-men I am : so handsome