原文地址
替换
创建 dog.txt
文件,输入如下内容
I have a dog, my cat's name is xxx.
I love my dog.
My dog love my too.
My dog was 2 years old.
替换每一行中第一次出现的 dog
为 cat
。(注 在替换的时候,不仅仅是 /
可作为分隔符, 其他字符也可作为分隔符, 只需要前后的分隔符一致即可)
sed 's/dog/cat/' dog.txt
结果为:
I have a cat, my cat's name is xxx.
I love my cat.
My cat love my too.
My cat was 2 years old.
全部替换
g
表示把左右的 dog
替换为 cat
。
$ sed 's/dog/cat/g' dog.txt
结果为:
I have a cat, my cat's name is xxx.
I love my cat.
My cat love my too.
My cat was 2 years old.
替换指定内容
替换第2行
$ sed "2s/dog/cat/g" dog.txt
I have a dog, my cat's name is xxx.
I love my cat.
My dog love my too.
My dog was 2 years old.
替换3-5行
$ sed '3,5s/dog/cat/g' dog.txt
I have a dog, my cat's name is xxx.
I love my dog.
My cat love my too.
My cat was 2 years old.
替换最后一行
$ sed '$s/dog/cat/g' dog.txt
I have a dog, my cat's name is xxx.
I love my dog.
My dog love my too.
My cat was 2 years old.
替换第2行到最后一行
$ sed '2,$s/dog/cat/g' dog.txt
I have a dog, my cat's name is xxx.
I love my cat.
My cat love my too.
My cat was 2 years old.
只替换每一行第一个o
$ sed 's/o/O/1' dog.txt
I have a dOg, my cat's name is xxx.
I lOve my dog.
My dOg love my too.
My dOg was 2 years old.
只替换每一行第一个o
sed 's/o/O/2' dog.txt
I have a dog, my cat's name is xxx.
I love my dOg.
My dog lOve my too.
My dog was 2 years Old.
替换源文件
使用 -i
参数编辑源文件
sed -i "s/dog/cat/g" dog.txt
在 Mac
上会出现如下错误
sed: 1: "dog.txt": extra characters at the end of d command
原因:
sed
编辑源文件的时候,需要指定一个文件后缀,sed
把源文件添加后缀后进行备份,如果后缀名称长度为 0 ,则不会进行备份。
Edit files in-place, saving backups with the specified extension.
If a zero-length extension is given, no backup will be saved. It
is not recommended to give a zero-length extension when in-place
editing files, as you risk corruption or partial content in situ-
ations where disk space is exhausted, etc.
解决方式: 添加长度为 0
的后缀名称。
sed -i '' "s/dog/cat/g" dog.txt
正则表达式
-
^
表示一行的开头。如:/^#/
以#
开头的匹配。 -
$
表示一行的结尾。如:/}$/
以}
结尾的匹配。 -
\<
表示词首。 如:\
表示以 abc
为首的词。 -
\>
表示词尾。 如:abc\>
表示以abc
结尾的词。 -
.
表示任何单个字符。 -
*
表示某个字符出现了0次或多次。 -
[ ]
字符集合。 如:[abc]
表示匹配a或b或c,还有[a-zA-Z]
表示匹配所有的26个字符。如果其中有^表示反,如[^a]
表示非a的字符。 -
&
保存搜索字符用来替换其他字符,如s/love/-&-/
,love替换成-love-
。
多个匹配
-e
选项允许在同一行里执行多条命令:(第 1 行到第 3 行的 dog
替换成 cat
,第 3 行到最后一行的 My
替换成 Her
)
$ sed -e '1,3s/dog/cat/g' -e '3,$s/My/Her/g' dog.txt
I have a cat, my cat's name is xxx.
I love my cat.
Her cat love my too.
Her dog was 2 years old.
使用 &
来当做被匹配的变量, 在该变量左右添加其他字符
$ sed 's/My/**&**/g' dog.txt
I have a dog, my cat's name is xxx.
I love my dog.
**My** dog love my too.
**My** dog was 2 years old.
插入
在第 1 行上插入 I have a cat.
。(1 表示第1行, i 表示插入的意思。在 Mac 上, i\
之后需要换行,原因参考这里)
$ sed '1 I\
I have a cat. ' dog.txt
I have a cat. I have a dog, my cat's name is xxx.
I love my dog.
My dog love my too.
My dog was 2 years old.
追加
在最后一行追加 Test append.
。(在 Mac 上,a\
之后需要换行, 具体原因同上)
sed '$ a\
Test append.' dog.txt
I have a dog, my cat's name is xxx.
I love my dog.
My dog love my too.
My dog was 2 years old.
Test append.
删除操作
删除空白行:
sed '/^$/d' file
删除文件的第2行:
sed '2d' file
删除文件的第2行到末尾所有行:
sed '2,$d' file
删除文件最后一行:
sed '$d' file
删除文件中所有开头是test的行:
sed '/^test/'d file
Pattern Space
和 Hold Space
理解
sed
会逐行处理文件, 首先 sed
把当前正在处理的行保存在一个临时缓存区中(Pattern Space
),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed
每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed
便结束运行。
Hold Space
能够长期存贮 sed
读取的数据,当 sed 在其他行处理我们可以重用 Hold Space
空间里面的数据, 但是不能直接访问 Hold Space
内的数据,而是如果要对其执行某些操作,则需要将其复制或附加到 Pattern Space
。
g
: 将 hold space
中的内容拷贝到 pattern space
中,原来 pattern space
里的内容清除;
G
: 将 hold space
中的内容append到 pattern space
后
h
: 将 pattern space
中的内容拷贝到 hold space
中,原来的 hold space
里的内容被清除
H
: 将 pattern space
中的内容append到 hold space
后
x
: 交换 pattern space
和 hold space
的内容
使用如下示例文件
$ cat t.txt
one
two
three
反序输出文件每一行的内容:(参考sed 简明教程)
$ sed '1!G;h;$!d' t.txt
three
two
one
其中的 ‘1!G;h;$!d’ 可拆解为三个命令
- 1!G —— 只有第一行不执行G命令,将hold space中的内容append回到pattern space
- h —— 第一行都执行h命令,将pattern space中的内容拷贝到hold space中
- $!d —— 除了最后一行不执行d命令,其它行都执行d命令,删除当前行
参考资料:
sed use: expected context address
The concept of "Hold space" and "Pattern space" in sed
more than one number or g in substitute flags
sed命令
sed command