linux工具-sed
目录
1. 基本语法
1.1 sed名称由来
sed:Stream Editor, 文本流编辑.
1.2 入门例子
# 读取文件filename, 将每行(第一行到最后一行)做修改, 把abc替换为def.
# -e : sed选项, 表示sed的动作写在命令行(即单引号中的内容), 如果只是用单个-e, 则-e选项可以省略.
# 1, $ : address-range, sed-command只操作adress-range范围内的文本, 此处表示从第一行到最后一行. address-range可以省略, 表示处理整个文本.
# s/abc/def/ : sed-command, 对文本做的操作, 此处表示把abc替换为def.
# filename : 待处理文件.
sed -e '1, $ s/abc/def/' filename
1.3 语法格式
#完整格式
sed [-hnv][-e<script>][-f<script_file>] [text_file]
#-e格式, sed动作写在命令行
# [option] : sed选项.
# [address-range | pattern-to-match]: 指定sed-command操作的文本范围.
# sed-command : 对文本的操作.
sed [option] '[address-range | pattern-to-match] sed-command' filename
#-f格式, sed动作写在脚本文件sed_script_file
sed [option] -f sed_script_file filename
2. sed选项(option)
sed的主要option如下:
短选项 | 长选项 | 说明 |
---|---|---|
-e<script> | --expression=<script> | sed动作写在命令行,不使用脚本 (直接在命令行模式上进行sed的动作编辑), 与-f选项相对应. 此为默认选项. |
-f<script_file> | --file=<script_file> | sed动作写在一个脚本文件内, 例如:-f file.sed, 表示用file.sed来执行sed动作 |
-h | --help | 显示帮助 |
-n | --quit --silent |
只打印模式匹配的行, 默认情况下sed会把文件中所有行都打印出来. |
-r | 支持扩展的正则表达式. | |
-i | 直接修改文件内容, 默认情况下sed只修改输出到Terminal的内容. |
-e选项可以使用多个, 以执行多个操作
# 下例用了两个-e选项, 第一个删除匹配o的行, 第二个, 把3~5行中的h替换为k.
# 注意: 这两个动作(删除行和替换文本)是同时进行的, 所以第二个替换涉及的3~5行, 是指filename文件中的3~5行, 而不是删除匹配o的行之后的文本内容中的3~5行.
sed -e '/o/ d' -e '3, 5 s/h/k/' filename
3. sed动作
格式:'[address-range | pattern-to-match] sed-command'
sed动作分两部分 | 作用 |
---|---|
address-range或pattern-to-match | 指定文件中的一系列文本行,可以是特定范围内的行,也可以是匹配某模式的行. |
sed-command | 对上述的文本行进行处理. |
注意:
- sed动作要写在一对单引号中,防止被shell解释为其它命令.
- sed动作的两部分之间可以有空格,也可以没空格.
- address-range | pattern-to-match是可选的,如果不指定,默认是文件中的所有行.
3.1. address-range | pattern-to-match
作用:指定文件中的一系列文本行,默认为文本中的所有文本行.
格式:address-range可以通过行号指定,也可以通过/pattern/指定
addr-range or pattern | 说明 |
---|---|
m | 处理第m行,m为行号, $表示最后一行 |
/pattern/ | 处理匹配/pattern/的行 |
m, n | 处理m到n范围内的所有行,m/n为行号,逗号两边可以加空格 |
/pattern1/, /pattern2/ | 处理匹配/pattern1/和/pattern2/范围内的所有行 |
m, /pattern/ | 处理第m行~匹配/pattern/范围内的所有行. |
/pattern/, n | 处理匹配/pattern/~第n行范围内的所有行. |
m, n! | 反向选择, 处理m~n行之外的行. |
例子:
3.1.1 待处理文件内容:
$ cat a.txt # 文件内容
line first
line second
line third
line forth
line fifth
line sixth
line seventh
3.1.2 通过行号指定行
注意: $表示最后一行
$ sed -n '3 p' a.txt # 打印第3行到Terminal
line third
$
$ sed -n '3,5 p' a.txt # 打印第3~5行到Terminal
line third
line forth
line fifth
$
$ sed -n '3, $ p' a.txt # 打印第3~最后行到Terminal
line third
line forth
line fifth
line sixth
line seventh
3.1.3 通过pattern指定行
$ sed -n '/ne third/,/ne fifth/ p' a.txt # 打印匹配 /ne th/和/ne fi/ 之间的行到Terminal
line third
line forth
line fifth
$
$ sed -n '3,/ne fif/ p' a.txt
line third
line forth
line fifth
$ sed -n '/ne third/,5 p' a.txt
line third
line forth
line fifth
3.1.4 反选,指定3~5行之外的行.
$ sed -n '3,5! p' a.txt # 打印第3~5行之外的行到Terminal
line first
line second
line sixth
line seventh
3.1.5 如果第二个pattern没匹配到,则打印到文件结尾
$ sed -n '/ne third/,/xxxx/ p' a.txt # 如果第二个pattern没匹配到,则打印到文件结尾
line third
line forth
line fifth
line sixth
line seventh
3.1.6 如果第一个pattern没匹配到,则匹配结果为空
$ sed -n '/xxxx/,/ne fift/ p' a.txt # 如果第一个pattern没匹配到,则匹配结果为空
$
3.2. sed-command
作用:对文本行进行处理.
常用sed命令如下:
操作 | 命令 | 说明 |
---|---|---|
打印 | p | 打印匹配行(通常和-n选项配合使用) |
= | 打印文件行号 | |
新增 | a\text | 在定位到的 "每一行" "后面" 附加新行text |
i\text | 在定位到的 "每一行" "前面" 附加新行text | |
删除 | d | 删除定位到的行 |
替换 | c\text | 指定范围内的文本替换为text |
s/pattern/text/ | 将行内匹配pattern的内容替换为text | |
读写文件 | w filename | 将文本写到filename文件中,类似于输出重定向 |
r filename | 从文件filename中读文本,类似于输入重定向 | |
退出 | q | 第一个模式匹配后退出 或 立即退出 |
多个命令 | {命令;命令…} | 执行多个命令, 命令间使用分号分隔开. |
... | ... | ... |
例子:
3.2.1 待处理文件内容:
$ cat a.txt # 文件内容
line first
line second
line third
line forth
line fifth
line sixth
line seventh
3.2.2 使用p命令,打印文本
$ sed -n '/ne th/,/ne fi/ p' a.txt
line third
line forth
line fifth
3.2.3 使用=命令,打印行号
$ sed -n '/ne th/,/ne fi/ =' a.txt
3
4
5
3.2.4 使用a命令,在每个匹配行后面追加一行文本
# 注意下面命令没有使用-n选项, 所以默认打印所以行, 并在address-range中行后添加新行new
$ sed '/ne th/,/ne fi/ a\new' a.txt
line first
line second
line third
new
line forth
new
line fifth
new
line sixth
line seventh
3.2.5 使用i命令,在每个匹配行前面追加文本
$ sed '/ne th/,/ne fi/ i\new' a.txt
line first
line second
new
line third
new
line forth
new
line fifth
line sixth
line seventh
3.2.6 使用c命令,将匹配到的address-range行替换为新文本
注意: 不是每行替换一份,而是整个address-range替换为一份.
$ sed '/ne th/,/ne fi/ c\new' a.txt
line first
line second
new
line sixth
line seventh
3.2.7 使用d命令,删除匹配的行
$ sed '/ne th/,/ne fi/ d' a.txt
line first
line second
line sixth
line seventh
3.2.8 使用s命令,替换匹配行内容的文本
$ sed '/ne th/,/ne fi/ s/line/Number/' a.txt
line first
line second
Number third
Number forth
Number fifth
line sixth
line seventh
3.2.9 使用多个命令
# 找到匹配o的行, 把o替换为k, 并打印该行, 多个命令写在花括号中, 并以分号分隔, 中间可以加空格
$ sed -n '/o/ {s/o/k/; p}' a.txt
line secknd
line fkrth
3.2.10 使用q退出
# 找到匹配o的行, 把o替换为k, 并打印该行, 并退出,
# 由于有q命令, 所以操作完第二行后就退出, 不在处理第四行(第四行也匹配o).
$ sed -n '/o/ {s/o/k/; p}' a.txt
line secknd
4. /pattern/支持的正则
4.1 元字符
字符 | 说明 |
---|---|
. | 任意字符(换行符除外) |
\w | 字母, 数字, 下划线, 汉字 |
\s | 空白符 |
\d | 数字 |
\b | 单词边界(开始或结束) |
^ | 行首(当前字符串开始) |
$ | 行尾(当前字符串结尾) |
举例
# 使用.\+, 表示任意字符重复1次或多次(注意, 表示+需要用\+, 表示*直接用*)
echo "execute fail" | sed -e '1, $ s#te.\+#te pass#' # execute pass
# 使用\s\+\w\+, 表示多个空白后面跟多个\w
echo "execute fail" | sed -e '1, $ s#te\s\+\w\+#te pass#' # execute pass
# 使用\b, 这样e\b会定位到execute最后的e, 而不会匹配开头和中间的e.
echo "execute fail" | sed -e '1, $ s#e\b.*#e pass#' # execute pass
4.2 重复(量词)
量词 | 说明 | 注意 |
---|---|---|
* | 重复0次或更多次 | |
+ | 重复1次或更多次 | 注意要使用\+ |
? | 重复0次或重复1次 | 注意要使用\? |
{m} | 重复m次 | 注意要使用\{m\} |
{m,} | 重复m次或更多次 | 注意要使用\{m, \} |
{m,n} | 重复m次到n次 | 注意要使用\{m, n\} |
非贪婪匹配(懒惰匹配), 不过看起来sed中的非贪婪匹配不好使.
a\w*?b, 以a开头, 以b结束的字符串.
对于字符串aabab,
如果用a\w+b, +会匹配尽可能多的字符, 所以会匹配到aabab.
如果用a\w+?b, +?会匹配尽可能多的字符, 所以会匹配到aab.
4.3 字符转义
查找大部分元字符本身或量词本身等特殊字符时, 需要转义, 比如:
\. \* \\ 等, 表示本身时需要转义, 表示特殊意义时不需要转义.
但, 表示有一些特殊字符本身不需要转义:
+ ( ) { } 等, 表示本身时不需要转义, 表示特殊意义时需要转义.
4.4 自定义字符集
在方括号中写一系列字符, 表示匹配这些字符中的任意一个:
举例 | 说明 |
---|---|
[aeiou] | 任意元音字母 |
[0-9] | 任意数字, -表示范围 |
[_0-9a-zA-Z] | 等价于\w |
举例
# 使用字符集, 中括号不需要转义
echo "execute fail" | sed -e '1, $ s#e\b\s*[a-z]\+#e pass#' # execute pass
4.5 分支与分组
分支: \d{5}-\d{4}\|\d{5}, 中间的|表示"或", 匹配左边(五位数字-四位数字)或匹配右边(五位数字)都可以.
注意, |需要转义, 使用\|
分组: \(\d{3}\.\){4}, 将一组字符(\d\d\d\.)重复4次.
注意, ()需要转义, 使用\(\)
4.6 取反
代码 | 说明 |
---|---|
\W | 非\w的字符 |
\S | 非\s的字符 |
\D | 非\d的字符 |
\B | 非\b的字符 |
[^x] | 非x的字符 |
[^aeiou] | 元音字符以外的字符 |
4.7 后向引用(向前引用)
# 向前引用, \1表示前面第一个圆括号中的内容.
echo "abc abc abc x" | sed -e '1, $ s#\(\w\+\) \1 \1#\1#' # abc x
5. 在sed命令中进行变量替换
$ VAR="var0"
$ text="1234,abcd"
$ echo $text | sed 's/abcd/$VAR/' # 在单引号中变量替换不成功
1234,$VAR
$ echo $text | sed "s/abcd/$VAR/" # 在双引号中变量替换成功
1234,var0
$
待完成