sed的使用方法¶
格式:
sed [-nefr] [n1, n2] action
[n1, n2]选项:
不一定需要, 选择要处理的行。如10,20表示在10~20行之间处理
action选项支持如下参数:
* a: 表示添加,后接字符串,添加到当前行的下一行
* c: 表示替换,后接字符串,用它替换n1到n2之间的行
* d: 表示删除符合模式的行,它的语法为 ``sed '/regexp/d'``, 斜杠之间是正则表达式,模式在d前面,d后面一般不接受任何内容
* i: 表示插入,后接字符串,添加到当前行的上一行
* p: 表示打印,打印某一选择的数据,通常与 ``-n`` 选项一同使用
* s: 表示搜索,还可以替换,类似于Vim里的搜索替换功能。如:
``1,20s/old/new/g`` 表示替换1~20行的old为new,g在这儿表示处理这一行所有匹配的内容
参数介绍:
-n, --quiet, --silent
安静模式,只有经过Sed处理过的行才显示出来,其他不显示
-e script, --expression=script
表示直接在命令行上进行Sed操作,默认选项,不用写
-f script-file, --file=script-file
将Sed操作写在一个文件里,用的时候-f filename就可以按照内容进行Sed操作了
-i[SUFFIX], --in-place[=SUFFIX]
直接在文件中编辑(和 ``-f`` 参数不同点在于, 它直接在文件中替换) (makes backup if extension supplied)
-r, --regexp-extended
表示Sed支持扩展正则表达式
实例:
//删除
"."表示任意字元;
"*" 表示其前字元可重任意次
//它们结合 ".*" 表示两 "t" 字母间的任意字串)
10d //删除档内第 10 行资料
/man/d //删除含有 "man" 字串的资料行
10,200d //删除档内第 10 行到第 200 行资料
10,/man/d //删除档内第 10 行到含 "man" 字串的资料
/t.*t/d //删除所有含两 "t" 字母的资料行
/apple/,/orange/d
文件操作:
// 将文件中含 "machine" 字串的资料行中的 "phi" 字串
// 替换成为 "beta" 字串。其命令列如下
sed -e '/machine/s/phi/beta/g' input.dat
//将文件中第 5 行资料 , 替换成句子 "Those must often wipe a bloody nose":
sed -e '5c Those must often wipe a bloody nose' input.dat
将文件中 1 至 100 行的资料区 , 替换成如下两行资料aaaa\nbbbb:
sed -e '1,100c aaaa\nbbbb' input.dat
将文件中含 "phi" 字串的资料行 , 搬至 mach.inf 档中储存:
sed -e '/phi/w mach.inf' <文档>
将 ``mach.inf`` 文件内容 , 搬至<文档>中含 "beta" 字串的资料行:
sed -e '/beta/r mach.inf' <文档>
删除文件中的资料:
将文件内所有空白行全部删除:
sed -e '/^$/d' <文档>
将文件内连续的空白行, 删除它们成为一行:
sed -e '/^$/{
N
/^$/D
}' <文档>
# 函数参数 N表示: 将空白行的下一行资料添加至pattern space内
# 函数参数 /^$/D 表示: 当添加的是空白行时, 删除第一行空白行, 而且剩下的空白行则再重新执行指令一次
# 指令重新执行一次, 删除一行空白行, 如此反覆直至空白行後添加的为非空白行为止, 故连续的空白行最後只剩一空白行被输出
搜寻文件中的资料:
将文件中含有 "gamma" 字串的资料行输出:
sed -n -e '/gamma/p' <文档>
使用 -f
选项操作:
将文件中的前 100 资料, 搬到文件中第 300 後输出。其命令列如下:
sed -f mov.scr <文档>
# mov.scr的内容为
1,100 {
H
d
}
300G
# 它表示将文件中的前100资料 , 先储存在 hold space,後删除
# 将 hold space 内的资料 , 添加在文件中的第300
显示passwd内容,将2~5行删除后显示:
cat -n /etc/passwd | sed '2,5d'
在第2行后面加上Hello China字符串:
cat -n /etc/passwd | sed '2a Hello China'
将2~5行的内容替换为“Hello China”:
cat -n /etc/passwd | sed '2,5c Hello China'
只显示5~7行,注意 p,-n
的配合使用:
cat -n /etc/passwd | sed -n '5,7p'
得到eth0的ip(^.* addr://g'
指把从开头到addr:的替换为空, s/Bcast.*$//g
指把以Bcast开头的到最后的替换为空):
ifconfig eth0 | grep 'inet ' | sed 's/^.* addr://g' | sed 's/Bcast.*$//g'
删除 yel.dat 内 1 至 10 行资料 , 并将其余文字中的 “yellow” 字串改成 “black” 字串:
sed -e '1,10d' -e 's/yellow/black/g' yel.dat
打印出 white.dat 档内含有 “white”字串的资料行:
sed -n -e '/white/p' white.dat
把文件 <fileName>
中手机号前面有区号的区号去掉(注意直接使用 \2
就是取第二个):
sed -e 's/\(0[0-9]\{2,3\}\)\([0-9]\{11\}\)/0\2/g' ./<fileName>
linux专用实例¶
1.把,改为换行符
echo "a,b,c,d" |sed 's/,/\n/g'
2.把,改为换行符,再换回来
# 这种是错误的
echo "a,b,c,d" |sed 's/,/\n/g'|sed 's/\n/,/g'
# 用tr可实现
echo "a,b,c,d" |sed 's/,/\n/g'|tr -t '\n' ','
# 非用sed方法为
echo "a,b,c,d" |sed 's/,/\n/g'|sed ':label; N; s/\n/,/; b label'
说明:
:label; 这是一个标签,用来实现跳转处理,名字可以随便取(label),后面的b label就是跳转指令
N; N是sed的一个处理命令,追加文本流中的下一行到模式空间进行合并处理,因此是换行符可见
s/\n/,/; s是sed的替换命令,将换行符替换为,号
b label 或者 t label b / t 是sed的跳转命令,跳转到指定的标签处
实践¶
实践1-基本:
1. 把文件 ``<fileName>`` 中的 ``($session[0]['id']`` 修改为 ``($session[0]['user_id']``
$ sed -i "s/(\$session\[0]\['id']/(\$session\[0]\['user_id']/g" ./<fileName>
2. 把文件/etc/fstab中含有' swap '的行前面加#符合注释
$ sed -i '/ swap / s/^/#/' /etc/fstab
把当前项目中的 github.com/docker
替换为 docker.io
files=( $(find . -name '*.go' -not -path './vendor/*') ) // 详情参见find命令
for rule in \
's|"github.com/docker/docker/api|"docker.io/go-docker/api|' \
's|^([[:space:]]+)"github.com/docker/docker/client|\1client "docker.io/go-docker|' \
's|"github.com/docker/docker/client|"docker.io/go-docker|' \
; do
sed -i -E "$rule" ${files[*]}
done
把指定文件夹./files下的 ./files
替换为 /files/k8s/yamls
$ sed -i -e "s/\.\/files/\/files\/k8s\/yamls/g" `grep -rl "./files" .`
实例: 把指定文件下的 PACKAGE_NAME
换成指定值:
$ cat << EOF > replace.sh
SRC_FILE=${1}
DES_FILE=${2}
PACKAGE=${3}
sed 's/PACKAGE_NAME/'"${PACKAGE}"'/g' ${SRC_FILE} > ${DES_FILE}
使用:
$ zsh replace ./src.txt ./des.txt <replace text>
常见问题¶
Mac sed与GNU sed之间的区别¶
https://qastack.cn/unix/13711/differences-between-sed-on-mac-osx-and-other-standard-sed
d, +等都不能用¶
可行的命令:
$ sed -n '/^.*[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*.*$/p' file.txt
不可行的命令:
$ sed -n '/^.*\d+\.\d+\.\d+\.\d+.*$/p' file.txt