在各项工作,需要大量的文本处理。有时,想把文件按行翻转一下,最后一行显示在第一行,倒数第二行显示在正数第二行,等等。这是行的逆转要求,可以通过命令tac对文件操作,达到目的;有时,想把一行内容按单词翻转一下,最后一个单词显示第一个位置,倒数第二个单词显示在正数第二个位置,等等。这是对单词的逆转要求,可以通过命令awk对行操作,达到目的;有时,想把一个单词或任意字符串按字符翻转一下,最后一个字符与第一字符对换,等等。这是对字符的逆转要求,可以通过命令rev对字符串操作,达到目的。
本文针对这三类要求,通过sed流编辑器,进行操作处理,达到翻转、调换的功能。主要借助s替换操作、G、D等命令完成。
一、替换功能
sed重要作用体现在其强大的替换功能上。
仅举简单而典型的几例为证。
1.字符串间加空格
echo 12345|sed 's/./& /g'
2.字符串反向输出
echo abc|sed -r 's/(.)(.)(.)/\3\2\1/'
3.字符串按列输出
echo ABCD|sed 's/./&\n/g'
4.字符串由列转行(有空格)
seq 4|sed ':a;N;s/\n/ /g;ba'
5.字符串由列转行(无空格)
seq 4|sed ':a;N;s/\n//g;ba'
二、逆转功能
我们对文本文件的递转操作有三类:字符串或单词反向输出、行内单词的反向输出和文件的反向输出。其中两个常用命令rev和tac,可以完成字符串反向输出(rev)、文件的反向查看输出(tac)。工作中可以用此完成小目标。
本文的学习与讨论更多地是知识的扩展与思维的发散!
1.单词按字符逆转
a.字符左取右放
需求:将centos7 反向输出 :7sotnec
方法:echo 'centos7'|sed –r '/\n/!G;s/([^ ])(.*\n)/&\2\1/;//D;s/\n//'
([^ ])可以用(.)代替。命令执行过程在后面阐述!
列出另一种处理方法(理解即可)
echo 12345 |sed -r 's/.*/&\n/g;:a;s/(.*)(.)\n(.*)/\1\n\3\2/g;ta;s/^\n//g'
b.字符由行变列
(1)tac tr
字符串变成1列,用tac反转,再由列变为行
echo 'linux'|sed 's/./&\n/g'|tac|tr -d "\n"
(2)tac xargs
echo 'unix'|sed 's/./&\n/g'|tac|xargs |sed 's/ //g'
(3)tac
echo 'win'|sed 's/./&\n/g'|tac|sed ':a;N;s/\n//;ba'
(4)sed
echo 123456|sed 's/./&\n/g'|sed $'x;H;$!d;${x;s/\\n//g;}'
2.行按单词逆转
a.常用命令组合实现
echo {1..5}|xargs -n1|tac|xargs
echo "I love study"|xargs -n1|tac|xargs
b.sed实现
echo "I love linux !"|sed –r '/\n/!G;s/([^ ]* )(.*\n)/&\2\1/;//D;s/\n/ /'
命令解析:此方法关键在D参数。
有大写的N P D G H等命令,表示命令执行在多行模式空间中,与单行模式空间(默认的模式空间)有许多不同:
正常情况下,sed读取文件一行内容,在缓冲区(称为模式空间)中按sed命令顺序对文件的行进行文本处理。当使用n或N命令时,sed流编辑器会读取两行(或循环读取多行),一起处理。此时有别于单行模式空间,称为多行模式空间。
D命令就是删除多行模式空间中的第一行。如果D删除后,多行模式空间中还有剩余行,则返回D之前的命令(指D命令前的、' '中的第一条命令),重新执行;如果D删除后,(一般,此时多行模式空间转为单行模式空间)中没有任何内容,则将退出sed命令,将控制权交给sed流编辑器,在没有-n参数时,sed会输出模式空间中的内容。
D命令会引起循环,如果D被执行,那么D后面的命令是不会被执行的。
//是一种简写,表示与前面匹配一样,省略了匹配的内容。
sed命令执行过程:
各命令由分号;分开。从左向右顺序执行(有循环会打断命令的顺序)。
第一次执行“/\n/!G”命令,因没有\n换行符,要执行G,因为保留空间中为空,所以在模式空间追加一空行,此时单行模式空间变为多行模式空间,其空间内容为:
多行模式空间第一行:I love linux !\n
多行模式空间第二行:\n
然后,执行后面的替换“s/([^ ] )(.*\n)/&\2\1/”
多行模式空间第一行:I love linux !\n
多行模式空间第二行:love linux !\nI \n
执行“//D”//匹配(第一行替换执行到第二行)成功,执行D删除多行模式空间第一行。成功执行D命令,将检查多行模式空间中的内容:有内容,意味着开始循环过程,重新执行前面的命令(仍然从第一条命令开始执行);没有内容,执行D后命令。此时多行模式空间的情况是:
love linux !\nI \n(\n是换行符)
多行模式空间第一行:love linux !\n
多行模式空间第二行:I \n
因为还有内容,返回前面命令
第二次执行"/\n/!G"命令,因第二行有\n不执行,内容不变
执行后面的替换“s/([^ ] )(.*\n)/&\2\1/”
多行模式空间第一行:love linux !\n
多行模式空间第二行:linux !\nlove I\n
再次执行“//D”……
后面过程与前面基本一致,不再重复。
……
最后一次执行"/\n/!G"命令,因有\n而不执行,内容不变
多行模式空间第一行:!\n
多行模式空间第二行:linux love I \n
执行后面的替换“s/([^ ] )(.*\n)/&\2\1/”因为!后面没有空格所以不匹配,不执行
执行“//D” //不匹配,不执行D删除
此时多行模式空间结束循环,执行后面命令:“s/\n/ /”
!\nlinux love I\n执行替换操作,最后结果:
! linux love I
3.文件按行逆转
tac命令:是将cat反写过来,他的功能就跟cat相反,cat是由“第一行到最后一行连续显示在屏幕上”,而tac则是“由最后一行到第一行反向在屏幕上显示出来”,可以自定义分割符号进行反转tac -s " " 若不自定义分割符,默认为“\n”。
利用sed流编辑器,同样可以实现文件反向输出。
准备素材:
sed '2,$G;h;$!d' filename
sed -n '1h;1!G;$!x;$p' filename
sed -n '1!G;h;$p' filename
小结
sed流编辑器功能强大,只有多通过项目训练,才能深入理解,应用时才能得心应手。
掌握多行模式空间的运用,才是真正达到sed的高级应用水平的最佳途径。