app开发者平台在数字化时代的重要性与发展趋势解析
791
2022-09-22
sed使用小结
对于行处理的工具,sed绝对是首选的。 sed处理文本过程如下:
sed一次处理一行内容,处理时,先读入一行,去掉尾部换行符,存入pattern space,执行编辑命令. 处理完毕,除非加了-n参数,把现在的pattern space打印出来,在后边打印曾去掉的换行符. 把pattern space内容给hold space,把pattern space置空,接着读下一行,处理下一行.
这让人感觉很抽象,sedsed的工具就是为了展现sed处理过程的。sedsed安装和使用都很简单,为了更好理解sed,装上sedsed工具是很有必要的。
wget touch /usr/local/bin/sedsed cat sedsed-1.0 >> /usr/local/bin/sedsed chmod 755 /usr/local/bin/sedsed
用法如下
usage: sedsed OPTION [-e sedscript] [-f sedscriptfile] [inputfile] OPTIONS: -f, --file add file contents to the commands to be parsed -e, --expression add the script to the commands to be parsed -n, --quiet suppress automatic printing of pattern space --silent alias to --quiet -d, --debug debug the sed script --hide hide some debug info (options: PATT,HOLD,COMM) --color shows debug output in colors (default: ON) --nocolor no colors on debug output --dump-debug dumps to screen the debugged sed script --emu emulates GNU sed (INCOMPLETE) --emudebug emulates GNU sed debugging the sed script (INCOMPLETE) -i, --indent script beautifier, prints indented and one-command-per-line output do STDOUT --prefix indent prefix string (default: 4 spaces) -t, --tokenize script tokenizer, prints extensive command by command information -H, --htmlize converts sed script to a colorful HTML page -f选项和sed的-f选项一样 -d打开debug,其中--hide表示隐藏指定的内容;如--hide=hold表示隐藏的保留空间缓冲区的内容 -i 的--indent 格式化复杂的sed脚本变成更加人性化的脚本
先看个简单的例子: [root@localhost ~]# cat 1.txt linux centos redhat linux ubuntu fedora 把linux换成debian,下面给出三种处理方式:sed处理;sedsed -d 和sedsed -d --hide
[root@localhost ~]# sed 's/linux/debian/g' 1.txt debian centos redhat debian ubuntu fedora [root@localhost ~]# sedsed -d 's/linux/debian/g' 1.txt PATT:linux$ HOLD:$ COMM:s/linux/debian/g PATT:debian$ HOLD:$ debian PATT:centos$ HOLD:$ COMM:s/linux/debian/g PATT:centos$ HOLD:$ centos PATT:redhat$ HOLD:$ COMM:s/linux/debian/g PATT:redhat$ HOLD:$ redhat PATT:linux$ HOLD:$ COMM:s/linux/debian/g PATT:debian$ HOLD:$ debian PATT:ubuntu$ HOLD:$ COMM:s/linux/debian/g PATT:ubuntu$ HOLD:$ ubuntu PATT:fedora$ HOLD:$ COMM:s/linux/debian/g PATT:fedora$ HOLD:$ fedora [root@localhost ~]# sedsed -d --hide=hold 's/linux/debian/g' 1.txt PATT:linux$ COMM:s/linux/debian/g PATT:debian$ debian PATT:centos$ COMM:s/linux/debian/g PATT:centos$ centos PATT:redhat$ COMM:s/linux/debian/g PATT:redhat$ redhat PATT:linux$ COMM:s/linux/debian/g PATT:debian$ debian PATT:ubuntu$ COMM:s/linux/debian/g PATT:ubuntu$ ubuntu PATT:fedora$ COMM:s/linux/debian/g PATT:fedora$ fedora
其中: PATT:sedsed输出显示模式空间缓冲区的内容 COMM:显示正在执行的命令 HOLD:显示hold sapce缓冲区的内容 sed的增删改查 sed用于删除操作的是:d和D 命令"d"作用是删除模式空间的内容,然后读入新的行,sed脚本从头再次开始执行. 命令"D"的不同之处在于它删除的是直到第一个内嵌换行符为止的模式空间的一部分,但是不会读入新的行,脚本将回到开始对剩下内容进行处理. 看个例子
[root@localhost ~]# cat 2.txt This line is followed by 1 blank line. This line is followed by 2 blank line. This line is followed by 3 blank line. This line is followed by 4 blank line. This is the end.
[root@localhost ~]# sed '/^$/{N;/^\n$/D}' 2.txt This line is followed by 1 blank line. This line is followed by 2 blank line. This line is followed by 3 blank line. This line is followed by 4 blank line. This is the end. [root@localhost ~]# sed '/^$/{N;/^\n$/d}' 2.txt This line is followed by 1 blank line. This line is followed by 2 blank line. This line is followed by 3 blank line. This line is followed by 4 blank line. This is the end.
用sedsed 打开debug看看执行过程 //后面的内容是我注释的
[root@localhost ~]# sedsed -d '/^$/{N;/^\n$/D}' 2.txt PATT:This line is followed by 1 blank line.$ //pattern空间读入第一行内容 HOLD:$ //hold空间开始为空 COMM:/^$/ { //正在执行的命令,判断是否为空行,很明显不是,所有不执行后面的命令,执行的结果送往屏幕并把结果给hold space. PATT:This line is followed by 1 blank line.$ HOLD:$ This line is followed by 1 blank line. PATT:$ //pattern空间读入第二行 HOLD:$ //hold空间开始还是为空 COMM:/^$/ { //正在执行的命令,判断是否为空行,很明显是,所有执行后面的命令 COMM:N //执行N读取下一行进入pattern空间 PATT:\nThis line is followed by 2 blank line.$ HOLD:$ //此时hold空间还是为空 COMM:/^\n$/ D //对pattern空间继续执行后面的命令:如果是空行,执行D命令,很明显不是,所有不执行。 PATT:\nThis line is followed by 2 blank line.$ //pattern空间内容 HOLD:$ //hold空间内容,任然为空。 COMM:} PATT:\nThis line is followed by 2 blank line.$ HOLD:$ This line is followed by 2 blank line. //由于没有满足执行条件,继续读取下一行。 PATT:$ //空行,满足执行条件,执行命令 HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ D //满足执行D命令条件,删除一空行(现在有两空行) PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\nThis line is followed by 3 blank line.$ HOLD:$ COMM:/^\n$/ D PATT:\nThis line is followed by 3 blank line.$ HOLD:$ COMM:} PATT:\nThis line is followed by 3 blank line.$ HOLD:$ This line is followed by 3 blank line. PATT:$ \\空行,满足命令执行条件,执行命令,读取下一行. HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ D \\满足执行D命令,删除一空行. PATT:$ \\空行,满足命令执行条件,执行命令,读取下一行. HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ D \\ \\满足执行D命令,删除一空行. PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\nThis line is followed by 4 blank line.$ HOLD:$ COMM:/^\n$/ D PATT:\nThis line is followed by 4 blank line.$ HOLD:$ COMM:} PATT:\nThis line is followed by 4 blank line.$ HOLD:$ This line is followed by 4 blank line. PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ D PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ D PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ D PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\nThis is the end.$ HOLD:$ COMM:/^\n$/ D PATT:\nThis is the end.$ HOLD:$ COMM:} PATT:\nThis is the end.$ HOLD:$ This is the end. [root@localhost ~]# sedsed -d '/^$/{N;/^\n$/d}' 2.txt PATT:This line is followed by 1 blank line.$ HOLD:$ COMM:/^$/ { PATT:This line is followed by 1 blank line.$ HOLD:$ This line is followed by 1 blank line. PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\nThis line is followed by 2 blank line.$ HOLD:$ COMM:/^\n$/ d PATT:\nThis line is followed by 2 blank line.$ HOLD:$ COMM:} PATT:\nThis line is followed by 2 blank line.$ HOLD:$ This line is followed by 2 blank line. PATT:$ \\空行,满足命令执行条件,执行命令,读取下一行. HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ d \\满足执行d命令条件,此时模式空间的两个空行都被删除. PATT:This line is followed by 3 blank line.$ HOLD:$ COMM:/^$/ { PATT:This line is followed by 3 blank line.$ HOLD:$ This line is followed by 3 blank line. PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ d PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\nThis line is followed by 4 blank line.$ HOLD:$ COMM:/^\n$/ d PATT:\nThis line is followed by 4 blank line.$ HOLD:$ COMM:} PATT:\nThis line is followed by 4 blank line.$ HOLD:$ This line is followed by 4 blank line. PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ d PATT:$ HOLD:$ COMM:/^$/ { COMM:N PATT:\n$ HOLD:$ COMM:/^\n$/ d PATT:This is the end.$ HOLD:$ COMM:/^$/ { PATT:This is the end.$ HOLD:$ This is the end.
一般情况下,都用d来删除,如:
删除空行: sed '/^\s*$/d' filename sed '/^[[:space:]]*$/d' filename 用行标示号来删除 sed 'n1d' filename 删除第n1行 sed 'n1,n2d' filename 删除第n1行到n2行间内容(n1<=n2) sed '5,$d' filename 删除第5行以后内容内容 用特殊匹配来删除,格式如下 sed '/regular_pattern/d' filename
sed基于行的插入和替换操作是由:a\,i\,c\来完成
a\命令是追加命令,追加将添加新文本到文件中当前行(即读入模式缓冲区中的行)的后面.所追加的文本行位于sed命令的下方另起一行.如果要追加的内容超过一行,则每一行都必须以反斜线结束,最后一行除外.最后一行将以引号和文件名结束. i\ 命令是在当前行的前面插入新的文本. c\ 用新的文本改变本行的文本
a\和i\用法比较简单,看一个c\的例子
[root@localhost ~]# cat 1.txt linux centos redhat linux ubuntu linux fedora [root@localhost ~]# sedsed -d '/linux/c\unix' 1.txt PATT:linux$ HOLD:$ COMM:/linux/ c\\N\unix unix PATT:centos$ HOLD:$ COMM:/linux/ c\\N\unix PATT:centos$ HOLD:$ centos PATT:redhat$ HOLD:$ COMM:/linux/ c\\N\unix PATT:redhat$ HOLD:$ redhat PATT:linux$ HOLD:$ COMM:/linux/ c\\N\unix unix PATT:ubuntu linux$ HOLD:$ COMM:/linux/ c\\N\unix unix PATT:fedora$ HOLD:$ COMM:/linux/ c\\N\unix PATT:fedora$ HOLD:$ fedora
sed的替换操作是用的最多的,用sed处理内容,最重要的就是要找特征数据(字符),并以此为基础处理内容而不会处理的内容过多或者处理不完全. 如最开始的举的把linux换成debian的例子. sed 的高级运用 打印匹配行号
[root@localhost ~]# cat 1.txt linux centos redhat linux ubuntu linux fedora [root@localhost ~]# sed -n '/^linux/=' 1.txt 1 4 [root@localhost ~]# sed -n '/^linux/{=;p}' 1.txt 1 linux 4 linux [root@localhost ~]# sedsed -d -n '/^linux/{=;p}' 1.txt PATT:linux$ HOLD:$ COMM:/^linux/ { COMM:= 1 PATT:linux$ HOLD:$ COMM:p linux PATT:linux$ HOLD:$ COMM:} PATT:linux$ HOLD:$ PATT:centos$ HOLD:$ COMM:/^linux/ { PATT:centos$ HOLD:$ PATT:redhat$ HOLD:$ COMM:/^linux/ { PATT:redhat$ HOLD:$ PATT:linux$ HOLD:$ COMM:/^linux/ { COMM:= 4 PATT:linux$ HOLD:$ COMM:p linux PATT:linux$ HOLD:$ COMM:} PATT:linux$ HOLD:$ PATT:ubuntu linux$ HOLD:$ COMM:/^linux/ { PATT:ubuntu linux$ HOLD:$ PATT:fedora$ HOLD:$ COMM:/^linux/ { PATT:fedora$ HOLD:$ [root@localhost ~]# sedsed -d '/^linux/{=;p}' 1.txt PATT:linux$ HOLD:$ COMM:/^linux/ { COMM:= 1 PATT:linux$ HOLD:$ COMM:p linux PATT:linux$ HOLD:$ COMM:} PATT:linux$ HOLD:$ linux PATT:centos$ HOLD:$ COMM:/^linux/ { PATT:centos$ HOLD:$ centos PATT:redhat$ HOLD:$ COMM:/^linux/ { PATT:redhat$ HOLD:$ redhat PATT:linux$ HOLD:$ COMM:/^linux/ { COMM:= 4 PATT:linux$ HOLD:$ COMM:p linux PATT:linux$ HOLD:$ COMM:} PATT:linux$ HOLD:$ linux PATT:ubuntu linux$ HOLD:$ COMM:/^linux/ { PATT:ubuntu linux$ HOLD:$ ubuntu linux PATT:fedora$ HOLD:$ COMM:/^linux/ { PATT:fedora$ HOLD:$ fedora
上面sedsed的调试显示了sed -n的参数的实际实现:禁止自动打印模式空间内容. sed 多行处理
sed多行处理是通过n和N来实现 多行Next(N)命令是相对next(n)命令的,后者将模式空间中的内容输出,然后把下一行读入模式空间,但是脚本并不会转移到开始而是从当前的n命令之后开始执行; 而前者则保存原来模式空间中的内容,再把新的一行读入,两者之间依靠一个换行符"\n"来分隔。在N命令执行后,控制流将继续用N命令以后的命令对模式空间进行处理. 值得注意的是,在多行模式中,特殊字符"^"和"$"匹配的是模式空间的最开始与最末尾,而不是内嵌"\n"的开始与末尾.
如下现在要将"Owner and Operator Guide"替换为"Installation Guide":
[root@localhost ~]# cat 3.txt Consult Section 3.1 in the Owner and Operator Guide for a description of the tape drives available on your system. [root@localhost ~]# sedsed -d --hide=hold '/Operator$/{n;s/Owner and Operator\nGuide /Installation Guide\n/}' 3.txt PATT:Consult Section 3.1 in the Owner and Operator$ COMM:/Operator$/ { COMM:n Consult Section 3.1 in the Owner and Operator PATT:Guide for a description of the tape drives$ COMM:s/Owner and Operator\nGuide /nstallation Guide\n/ PATT:Guide for a description of the tape drives$ COMM:} PATT:Guide for a description of the tape drives$ Guide for a description of the tape drives PATT:available on your system.$ COMM:/Operator$/ { PATT:available on your system.$ available on your system. [root@localhost ~]# sedsed -d --hide=hold '/Operator$/{N;s/Owner and Operator\nGuide /Installation Guide\n/}' 3.txt PATT:Consult Section 3.1 in the Owner and Operator$ COMM:/Operator$/ { COMM:N PATT:Consult Section 3.1 in the Owner and Operator\nGuide for a descr\ iption of the tape drives$ COMM:s/Owner and Operator\nGuide /nstallation Guide\n/ PATT:Consult Section 3.1 in the nstallation Guide\nfor a description \ of the tape drives$ COMM:} PATT:Consult Section 3.1 in the nstallation Guide\nfor a description \ of the tape drives$ Consult Section 3.1 in the nstallation Guide for a description of the tape drives PATT:available on your system.$ COMM:/Operator$/ { PATT:available on your system.$ available on your system.
sed用于把文本读入模式空间或者模式空间的内容写入到指定文本中. sed把模式空间的内容写入到指定文本中:由w和W实现 w filename:Write the current pattern space to filename. W filename:Write the first line of the current pattern space to filename. 如下:
[root@localhost ~]# cat 1.txt linux server centos redhat linux web ubuntu linux fedora [root@localhost ~]# sed -n '/^linux/,/^linux/w a.txt' 1.txt [root@localhost ~]# cat a.txt linux server centos redhat linux web
sed把文本读入模式空间由r实现
[root@localhost ~]# cat 1.txt linux server centos redhat linux web ubuntu linux fedora [root@localhost ~]# sed '/centos/r /root/1.txt' 1.txt linux server centos linux server centos redhat linux web ubuntu linux fedora redhat linux web ubuntu linux fedora
sed高级流控制
b 分支:无条件转移 ,分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾. t 有条件的转移,if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾. T 有条件的转移,错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾.
[root@localhost ~]# cat 4.txt a b c a d a a a s d d d x s a h j s a s h j h j d f j a s j k j 要求:删除行内与第一列字符重复的字符,shell、sed、awk各写一个。达到这个结果: a b c d s d d d x a h j s a s j j d f a s k 这个例子来自 a b c d s d d d x a h j s a s j j d f a s k [root@localhost ~]# sedsed -d --hide=hold ':a;s/^\(.\)\(.*\) \1/\1\2/;ta' 4.txt PATT:a b c a d a a a$ COMM::a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:a b c a d a a$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:a b c a d a$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:a b c a d$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:a b c d$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:a b c d$ COMM:t a PATT:a b c d$ a b c d PATT:s d d d x s a$ COMM::a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:s d d d x a$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:s d d d x a$ COMM:t a PATT:s d d d x a$ s d d d x a PATT:h j s a s h j h$ COMM::a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:h j s a s h j$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:h j s a s j$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:h j s a s j$ COMM:t a PATT:h j s a s j$ h j s a s j PATT:j d f j a s j k j$ COMM::a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:j d f j a s j k$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:j d f j a s k$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:j d f a s k$ COMM:t a COMM:s/^\(.\)\(.*\) \1/\1\2/ PATT:j d f a s k$ COMM:t a PATT:j d f a s k$ j d f a s k 附加两种其他的解法 while read a b;do echo "$a ${b// $a}";done <4.txt awk '{a=$1;gsub(" ?"a,"");print a""$0}' 4.txt
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~