Home sed
Post
Cancel

sed

两个常用的基本选项

  • -n : quiet模式,默认情况下,sed会打印执行所有动作后文本的全部内容,加上-n后,仅显示有命令处理的相关行
  • -e : 指定一个sed要执行的动作(命令),如果只有一个命令,可以不写,有多个命令要执行时,分别都用-e指定,需要注意, 如果不用-e指定命令,sed命令会自动将后面紧跟的一个参数当做命令处理,可能对其他选项有影响,所以最好明确使用 -e选项来指定输入命令(动作)。
  • -f : 指定命令集文件,如果要执行的动作比较多,如何写在命令行,就需要多个-e选项来指定。也可以直接使用-f指定动作文件,从文件中批量获取执行动作。比较方便。
  • -i : 直接在文件上修改,而不是仅显示预览效果,会对文件产生修改,一般先预览,确认后可以在加该参数。
  • -i[SUFFIX] : -i参数后面可以跟一个扩展,会额外将输入文件复制一个备份,备份文件的名称为 ”源文件名+SUFFIX“,如-i.bak
  • -r or -E : 启用扩展正则表达式语法。sed的命令本身支持正则表达式,默认使用基本正则表达式(BRE)语法,使用-r后表示启用扩展正则表达式(ERE)语法, 在BRE中,一些常见的元字符如+?|等没有特殊含义,需要使用转义符\来表示它们的特殊含义。 在ERE中,元字符具有特殊含义,如+表示一个或多个、?表示零个或一个、|表示逻辑或等。使用时需要注意。
  • -s : 分别处理每个输入文件,而不是将它们视为单个连续的流。

输入源

sed命令可以从文件或标准输出中获取源,默认是当做流处理的。

文件:可以从单个文件,也可以从多个文件

1
2
3
sed 's/foo/bar/' file1.txt file2.txt file3.txt     # 默认当做一个输入流处理
sed 's/foo/bar/' -s file1.txt file2.txt file3.txt  # 独立处理每个文件 
sed 's/foo/bar/' *.txt                              # 支持通配符匹配文件名

标准输出:一般可以配合管道使用

1
2
# 将 a 替换为 my 后显示全部内容。
echo "this is a test string" | sed -e "s/a/my/g"

打印指定行相关内容

指定行打印

sed -n -e "${START_LINE},${END_LINE}p" ${FILE}

获取行号,可以使用grep或awk。

1
2
3
4
5
# 使用awk获取行号,根据匹配的内容获取对应的行号
awk '/match_context/{print NR}' ${FILE}

# 使用grep ,配合-n参数,这个还需要进一步去掉后面的内容,可以使用awk来完成
grep -n "match_context" ${FILE} | awk -F: '{print $1}'

可以打印两个行之间的内容,也可以打印起始行之后n行的内容。

打印具有内容的相关行

打印具有香菇

1
2
3
4
5
6
7
8
9
sed -n "/${MATCH_STR}/p" ${FILE}

# example
$ cat ./st.txt 
aaa bbb ccc
111 222 333
last line
$ sed -n "/22/p" ./st.txt 
111 222 333

删除内容

删除具体某行 或 a到b行

1
2
3
4
5
6
7
# 操作原文件
sed -i "${LINENO}d" ${FILE}
sed -i "${START_LINE},${END_LINE}d" ${FILE}

# 预览效果
sed -e "${LINENO}d" ${FILE}
sed -e "${START_LINE},${END_LINE}d" ${FILE}

删除最后一行

1
sed -i '$d' ${FILE}

删除有特定匹配内容的行
如有匹配字符串${MATCH_STR},删除具有该字符串的行:

1
2
3
4
5
# 操作原文件
sed -i "/${MATCH_STR}/d" ${FILE}

# 预览效果
sed -e "/${MATCH_STR}/d" ${FILE}

追加内容

注意:是在匹配的内容所在行的下一行插入新的行,不是直接在后面添加内容

1
sed -e "/pattern/a additional_content" input.txt

example:

1
2
3
$ echo "aa bb cc" | sed -e "/bb/a my new addition"
aa bb cc
my new addition

替换内容

基本用法: s/匹配模式/替换字符串/[标志]

  • 匹配模式:是一个正则表达式模式,用于匹配要替换的文本。
  • 替换字符串:是替换后的字符串,用于替换匹配到的文本。
  • 标志:sed命令支持一些标志,用于修改替换行为。
    • g:全局替换标志,表示替换所有匹配到的文本,而不仅仅是第一个匹配项。
    • n:禁止默认输出,只打印经过替换后的结果。
    • p:打印替换行,并在默认输出之前打印原始行。

测试文本:

1
2
3
4
5
cat ./test.txt
aaa bbb ccc
11223344
abcd
last line

默认每行只替换第一个匹配的项

1
2
3
4
5
6
7
8
9
10
11
$ sed -e "s/a/z/" ./test.txt 
zaa bbb ccc
11223344
zbcd
lzst line

$ sed -n -e "s/a/z/p" ./test.txt 
zaa bbb ccc
zbcd
lzst line

全部提替

加上g标志即可。

1
2
3
4
5
6
7
8
9
10
11
$ sed -e "s/a/z/g" ./test.txt 
zzz bbb ccc
11223344
zbcd
lzst line

$ sed -n -e "s/a/z/pg" ./test.txt 
zzz bbb ccc
zbcd
lzst line

限定范围行

在s前加行号即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 仅对第一行替换
$ sed -e "1s/a/z/g" ./test.txt 
zzz bbb ccc
11223344
abcd
last line

$ sed  -n -e "1s/a/z/pg" ./test.txt 
zzz bbb ccc

# 两个行号之间,"1,3"即[1,3]行的行号范围
$ sed -e "1,3s/a/z/g" ./test.txt 
zzz bbb ccc
11223344
zbcd
last line

$ sed  -n -e "1,3s/a/z/pg" ./test.txt 
zzz bbb ccc
zbcd

特殊标记

特殊标记&

该标记表示与模式匹配的内容,可以用来方便的扩展匹配的文本字符串。

1
2
# 将 test 替换为 "test",加上双引号,双引号需要转义
echo "this is a test str" | sed -e "s/test/\"&\"/g"

特殊标记 \#

该标记用于表示 匹配字符串中的子字符串,上面的&一般只能用来扩展,不能在里面修改,使用\#或可实现。 \#中的#表示子字符串序号,具体指定为1,2,3,4这种,如 具体使用时,需要写为 \1\2\3这种。 子字符串使用 ()包围,()都需要转义,即实际使用\(substr\)表示一个子字符串,后面\1表示第一个 子字符串,\2表示第二个子字符串,以此类推。

该特殊标记可以操作子字符串,实现更复杂的替换操作,示例:

1
2
3
4
5
6
# 将 "apple is fruit" 替换为 "fruit is not only apple"
echo "as is known,apple is fruit" | sed -e "s/\(apple\) is \(fruit\)/\2 is not only \1/g"

# 还可以配合正则表达式等
echo "Name : John" | sed -e "s/\(Name\) : \(.*\)/\2 : \1/g"
echo "this year was 2020" | sed -e "s/year was \([0-9]*\)/year \1 was very substantial/g"

特殊标记 \<\>

用于精确匹配单词。

1
2
3
4
5
6
7
# 将单词 world 替换为 666,注意第一个helloworld是连在一起的,不是一个精确的world单词
echo "helloworld,this is linux world."| sed -e "s/\<world\>/666/g"
helloworld,this is linux 666.

#默认是不区分单词的,直接匹配
echo "helloworld,this is linux world."| sed -e "s/world/666/g"
hello666,this is linux 666.

其他

\n,\t分别是换行和制表符,也可以使用。

This post is licensed under CC BY 4.0 by the author.