sed举例
一直没有系统学习过
sed,这里是一些例子的汇总整理,快刀斩乱麻......
样例文本file内容如下
Cygwin
Unix
Linux
Solaris
AIX删除文件中指定行
例如删除第1行
sed '1d' file删除第3行
sed '3d' file上述
sed命令是直接将sed修改后的内容出处到标准输出(屏幕)上,而源文件不变。要更新源文件,需要加上-i参数。例如:
sed -i '3d' file
sed是将源文件复制后修改,所以-i参数实际是修改后覆盖源文件
在 sed 中, $ 代表最后一行,所以删除最后一行可以使用如下命令:
sed '$d' file此外, head 命令提供了一个更好的删除最后几行的方法, -n -X :通常 -n X 表示打印前X行,当 X 前面加上 - 则表示倒过来,即打印所有行但不包括最后的X行,也就是输出内容少了最后 X 行,所以定向到新文件就能截断原文件的最后 X 行(以下案例去除了file.txt文件的最后3行生成new_file.txt):
cat file.txt | head -n -3 > new_file.txt删除第2行到第四行
sed '2,4d' file保留第2行到第4行,删除其余行(反转选择就是加上!符号)
sed '2,4!d' file这里输出就是
Unix
Linux
Solaris删除第1行和最后一行(注意:每一行之间用;分隔)
sed '1d;$d' file同上,如果要删除第2行和第4行,就使用
'2d;3d'
匹配并删除
删除带有一个特定字符开头的行,例如,L开头的行
sed '/^L/d' file这里输出就是
Cygwin
Unix
Solaris
AIX删除x结尾的行
sed '/x$/d' file还支持正则,例如,要删除x或X结尾的行
sed '/[xX]$/d' file删除文件中的空白行
sed '/^$/d' file
^表示开头,$表示结尾,由于中间没有任何字符,就是空白行
删除空白行或者包含一些空格的行
sed '/^ *$/d' file这里
*表示0个或者多个重复的前一个字符,这里前一个字符是空格,所以这里*就表示有一个空格或者多个空格。此时会删除完全空白行,以及包含一个或多个空格的空白行。
删除全部是大写字符的行(这里会删除AIX行)
sed '/^[A-Z]*$/d' file
[A-Z]表示全部大写字母,后面跟了*表示前面的[A-Z]字符重复(任意大写字符),也就是表示整行都是大写字符,所以就删除了AIX
删除没有包含字符串Unix的行
sed '/Unix/!d' file删除包含Unix或Linux的行(或的符号是|,注意需要加转义符)
sed '/Unix\|Linux/d' file删除从第一行到匹配上Linux的行
sed '1,/Linux/d' file输出的结果是
Solaris
AIX删除从匹配Linux行到文档最后行
sed '/Linux/,$d' file如果最后一行包含了AIX,则删除最后一行(如果最后一行是其他内容则不删除)
sed '${/AIX/d;}' file输出内容是
Cygwin
Unix
Linux
Solaris这里
$表示最后一行,只在这行包含了AIX才删除,这里引入了if判断(也就是{}表示if条件)
如果最后一行包含了AIX或者HPUX则删除最后一行
sed '${/AIX\|HPUX/d;} file只在第1行到第4行之间出现Solaris字符串匹配情况下删除这行:
sed '1,4{/Solaris/d;}' file如果一行中包含了Unix关键字,则删除这行和下面一行
sed '/Unix/{N;d;}' file这里
N命令读取匹配行的下一行,而d命令则删除匹配行和下一行
上述命令输出是
Cygwin
Solaris
AIX只删除包含了Unix的下一行(但Unix行不删除)
sed '/Unix/{N;s/\n.*//;}' file输出内容是
Cygwin
Unix
Solaris
AIXsed - 25 examples to delete a line or pattern in a file原文还有3个例子较为复杂:
删除匹配行和匹配行之前的行
sed -n '/Linux/{s/.*//;x;d;};x;p;${x;p;}' file | sed '/^$/d'删除包含Linux的行之前的行,但不删除'Linux'行:
sed -n '/Linux/{x;d;};1h;1!{x;p;};${x;p;}' file删除包含Linux行以及之前的行和之后好的行
sed -n '/Linux/{N;s/.*//;x;d;};x;p;${x;p;}' file | sed '/^$/d'合并重复的空格成一个空格
在使用cut工具来截取ps出来的进程的pid,会遇到一个问题,就是每列之间的空格数量是不一定的,这样虽然可以通过awk来截取,但是蹪于cut命令就不行了。解决的方法是将多个空格合并成一个空格,sed命令提供了这个功能:
ps axu | grep '[j]boss' | sed 's/\s\+/ /g' | cut -d' ' -f2这里使用的是GNU sed,这个sed提供了
\s表示空格(扩展),\+表示多个空格
或者
ps axu | grep '[j]boss' | sed 's/\s\s*/ /g' | cut -d' ' -f2不过,在OS X中,需要传递
-E参数来激活sed扩展正则表达式,然后使用[[:space:]]来代替\s,也就是
ps axu | grep '[j]boss' | sed -E 's/[[:space:]]+/ /g' | cut -d' ' -f2请参考cut使用举例
替换换行符(): 读取整个文件替换换行符成一个空格
sed ':a;N;$!ba;s/\n/ /g'首先创建一个label
:a通过
N将当前行和下一行通过空格连接如果到了最后一行,则创建label
$!ba(这里$!表示不在最后一行做这个操作)最后使用在模式坑拜拜中的空格来替换每个换行符
上述方法实在太拗口,其实可以使用tr工具来实现这个任务
tr '\n' ' ' < input_filename或者
tr --delete '\n' < input.txt > output.txt在匹配行的最后添加内容
sed -i '/kernel \/boot/s/$/ clocksource_failover=acpi_pm/' /boot/grub/grub.cfg
sed -i '/vmlinuz-2.6.32/ s/$/ intremap=off/' /boot/grub/grub.conf上述方法简单来说就是先匹配,然后搜索到最后的标志
$,再进行替换。
参考
How to append a string at end of a specific line in a file in bash
Add to the end of a line containing a pattern - with sed or awk
将换行符替换成字符
例如,我有一个文件包含了多个主机名(每行是一个主机名),但是提交到某个平台的时候,格式要求使用,分隔,则可以通过sed来替换换行符
sed ':a;N;$!ba;s/\n/,/g' file含义如下:
创建一个标签(liabel)
:a通过添加
N到当前和下一行的位置如果在最后一行之前,则创建标签
$!ba($!表示如果最后一行就不做)最后将所有换行符替换成
,
上述命令是使用GNU sed,如果是跨平台,则使用BSD sed
sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/,/g'参考 How can I replace a newline (\n) using sed?
更为简单的方法是使用
tr,不过结尾多一个,
tr '\n' ',' < input_filename怎样去除最后一个字符,应该可以使用sed或awk,不过 Delete the last character of a string using string manipulation in shell script 提供了一个巧妙的方法,组合利用rev命令和cut命令。即先将字符串倒转(rev),然后用cut -c 2-截取出(n+1)-之后所有字符,然后再倒转回来
cat input_filename | tr '\n' ',' | rev | cut -c 2- | rev还有一种方法是使用bash 4.2之后,支持字符串变量切片
a=`cat input_filename | tr '\n' ','`
echo "${a::-1}"匹配行修改
例如我需要修改 /etc/fstab ,将包含 swap 行注释掉。参考 sed - Commenting a line matching a specific string AND that is not already commented out
原先的 /etc/fstab 内容如下:
...
UUID=57e88efb-83f7-42a3-8080-f943626bd7f7 swap swap defaults 0 0修改命令如下:
sed -i -e '/swap/s/^UUID=/#UUID=/g' /etc/fstab上述表示先匹配swap行,然后搜索 UUID= 开头的内容替换成 #UUID=
占位符替换思路
当需要向海量服务器部署配置脚本,但是配置脚本中某些字符串和服务器主机名相关(需要改成主机名),则可以模仿puppet之类的配置管理工具,采用配置文件中占位符方式来实现。
即预先分发的配置文件中包含一些特定的预先占好位置的变量字符串(具有特征,如全大写,或者有特殊符号),在分发完成后,采用pssh命令对配置文件中占位符变量进行替换。
举例:配置文件 /etc/example.conf 内容如下:
...
console name='HOSTNAME' dev='/dev/null' opts='-o example'
HOSTNAME就是需要替换的占位符变量
通过pscp分发完配置文件到所有服务器之后,就可以通过以下pssh命令将每个主机的主机名提取出来,然后用实际主机名替换HOSTNAME:
pssh -ih server_list "HOST=\$(hostname);sudo sed -i \"s/HOSTNAME/\$HOST/\" /etc/example.conf"sed多个匹配
sed支持一次检查多个匹配,实际上就是sed多个指令的意思。注意:指令之间使用;分隔:
sed -i '/PATTERN_1/d;PATTERN_2/d;PATTERN_3/d;/^$/d' myfile.txtsed转换文档实现unix2dos
unix2dos
sed 's/$'"/`echo \\\r`/" disk.txt > disk_dos.txtdos2unix
sed 's/^M$//' disk_dos.txt > disk.txt参考 HowTo: UNIX / Linux Convert DOS Newlines CR-LF to Unix/Linux Format
参考
Last updated
Was this helpful?