您的位置:首页 > 运维架构 > Linux

Linux文本处理命令--cut分割文件和sed查找替换的运用

2015-12-29 16:07 836 查看
今天遇到一个数据文件需要处理,文本约1万行,文件每行都是以$字符进行分隔的各种数据列,每行38列。我需要取其中的某一些列,基本都集中在前10列。最初的想法是使用UltraEdit工具进行处理,使用正则表达式查找出了每行中间所需要的内容,无奈UE只支持按行复制,无法单独复制匹配的部分。思来想去,打算到Linux下进行处理,顺便也复习一下常用的一些文本处理命令。Linux命令太强大了,问题果然几需要几步就迎刃而解了。

源文件列格式(以下为示例3行):

0202435718:79849391866393:D02502402$000236677201$00023667720101$D025024028727$D025024028727$D02502402$2015-06-08 13:36:07$0202435718$025301895457$         $0259000$10      $1020  $8727  $126894718$三星手机G9200(铂光金)$000061659$1.0   $D025  $8727$10032424 $20        $订单生效       $2015-06-08 13:36:07$20      $           $         $        $      $8727       $0$ZOR$2015-06-08 13:36:07$R1901001$$5288.0$$N$2015-06-08 13:37:59
6107547155:79849391865963:7089781102$000236677899$00023667789902$7016605928$7089781102$O22106565$2015-06-08 13:40:37$6107547155$6107547155$                $4320501$50      $2700  $9465  $121225083$格兰仕(Galanz)微波炉 P70F23P-G5(SO)$000070689$1.0$D002$0002$10038318$80$订单取消$2015-06-11 18:00:00$13$$$$$$0$ZOR$2015-06-08 13:40:37$R2201001$$399.0$MOBILE|02|01|3.0|10308$N$2015-06-08 13:40:36
6022048888:79849391866085:8091232198$000236678249$00023667824901$8016551693$8091232198$P22142344$2015-06-08 13:39:15$6022048888$6022048888$                $7720200$50      $3100  $9436  $109182779$kidsme亲亲我 摇铃组合牙刷 130065AE$000190BXL$1.0$D069$0001$10079703$70$订单拒收退$2015-06-10 18:00:00$14$$$$$K772020601$0$ZOR$2015-06-08 13:39:15$R9003035$$8.9$WAP$N$


我需要的内容为:

以$符为分隔,第3,5,6,7,8列并且将第7列日期格式由yyyy-mm-dd hh:mm:ss修改为yyyymmddhhmmss最终各列以,分隔

通过分析处理步骤,可知大致处理步骤为三步:

1.分割文件并取出需要的列;——使用cut命令

2.查找并替换日期格式;——使用sed命令

3.查找列分隔符$并替换为, ——使用sed命令

1. 文件分割

cut命令的用法:

[root@www ~]# cut -d '分隔字符' -f fields <==用于有特定分隔字符

[root@www ~]# cut -c 字符区间 <==用于排列整齐的讯息

选项与参数:

-d :后面接分隔字符。与 -f 一起使用;

-f :依据 -d 癿分隔字符将一段讯息分割成为数段,用 -f 取出第几段的意思;

-c :以字符 (characters) 的单位取出固定字符区间;

源文件文件名为source.txt,并上传至服务器:

[loguser@svcpreapp01 cut]$ ll
total 3524
drwxrwxr-x 2 loguser loguser    4096 Dec 29 16:31 ok
-rw-r--r-- 1 loguser loguser 3598763 Dec 29 16:30 source.txt


因文件行数较多,我们这里把结果文件输出到result.txt文件中,那么这里第一步我们需要使用的命令为:

cut -d '$' -f 3,5,6,7,8 source.txt > result.txt

[loguser@svcpreapp01 cut]$ cut -d '$' -f 3,5,6,7,8 source.txt > result.txt
[loguser@svcpreapp01 cut]$ ll
total 4208
drwxrwxr-x 2 loguser loguser    4096 Dec 29 16:31 ok
-rw-rw-r-- 1 loguser loguser  694021 Dec 29 16:33 result.txt
-rw-r--r-- 1 loguser loguser 3598763 Dec 29 16:30 source.txt
[loguser@svcpreapp01 cut]$


可以查看一下前10行的内容,看文件格式是否符合要求:head -n 10 result.txt

[loguser@svcpreapp01 cut]$ head -n 10 result.txt
00023667720101$D025024028727$D02502402$2015-06-08 13:36:07$0202435718
00023667789902$7089781102$O22106565$2015-06-08 13:40:37$6107547155
00023667824901$8091232198$P22142344$2015-06-08 13:39:15$6022048888
00023667938001$D002291287852$D00229128$2015-06-08 13:42:32$0101855315
00023667967601$D003101939312$D00310193$2015-06-08 13:44:07$6107554066
00023668329501$D000577509545$D00057750$2015-06-08 13:52:58$6016175500
00023668400101$D021609489358$D02160948$2015-06-08 13:54:58$6107422418
00023668457901$D004719687172$D00471968$2015-06-08 13:56:40$6100439132
00023668851801$4089771406$I22114577$2015-06-08 14:14:33$2214456603
00023668867701$1097223690$C23934507$2015-06-08 14:04:48$6107463339
[loguser@svcpreapp01 cut]$


如上,已经通过文件分割得到需要的文件

2. 文件查找替换

Linux下批量替换多个文件中的字符串的简单方法。用sed命令可以批量替换多个文件中的字符串。

命令如下:sed -i "s/原字符串/新字符串/g" `grep 原字符串 -rl 所在目录`

例如:我要把 charset=gb2312 替换为 charset=UTF-8,执行命令:sed -i "s/charset=gb2312/charset=UTF-8/g" `grep charset=gb2312 -rl /www`; 即可。

解释一下:

-i 表示inplace edit,就地修改文件

-r 表示搜索子目录

-l 表示输出匹配的文件名

这个命令组合很强大,要注意备份文件。

2.1 将日期格式由yyyy-mm-dd hh:mm:ss修改为yyyymmddhhmmss,即将-,空格和:替换为空即可:

替换命令为,其中查找的字符支持正则表达式匹配:sed -i "s/[- :]//g" result.txt

[loguser@svcpreapp01 cut]$ cp result.txt result-bak.txt
[loguser@svcpreapp01 cut]$ ll
total 4892
drwxrwxr-x 2 loguser loguser    4096 Dec 29 16:31 ok
-rw-rw-r-- 1 loguser loguser  694021 Dec 29 16:42 result-bak.txt
-rw-rw-r-- 1 loguser loguser  694021 Dec 29 16:33 result.txt
-rw-r--r-- 1 loguser loguser 3598763 Dec 29 16:30 source.txt
[loguser@svcpreapp01 cut]$ sed -i "s/[- :]//g" result.txt
[loguser@svcpreapp01 cut]$ head -n 10 result.txt
00023667720101$D025024028727$D02502402$20150608133607$0202435718
00023667789902$7089781102$O22106565$20150608134037$6107547155
00023667824901$8091232198$P22142344$20150608133915$6022048888
00023667938001$D002291287852$D00229128$20150608134232$0101855315
00023667967601$D003101939312$D00310193$20150608134407$6107554066
00023668329501$D000577509545$D00057750$20150608135258$6016175500
00023668400101$D021609489358$D02160948$20150608135458$6107422418
00023668457901$D004719687172$D00471968$20150608135640$6100439132
00023668851801$4089771406$I22114577$20150608141433$2214456603
00023668867701$1097223690$C23934507$20150608140448$6107463339
[loguser@svcpreapp01 cut]$
如上,已替换成功。

2.2 替换$字符

$字符在正则匹配的时候会认为是一行的结尾,因此需要使用转义,同时要注意使用单引号,如下,文件处理完成后即可得到想要的文件了:

[loguser@svcpreapp01 cut]$ sed -i 's/\$/,/g' result.txt
[loguser@svcpreapp01 cut]$ head -n 10 result.txt
00023667720101,D025024028727,D02502402,20150608133607,0202435718
00023667789902,7089781102,O22106565,20150608134037,6107547155
00023667824901,8091232198,P22142344,20150608133915,6022048888
00023667938001,D002291287852,D00229128,20150608134232,0101855315
00023667967601,D003101939312,D00310193,20150608134407,6107554066
00023668329501,D000577509545,D00057750,20150608135258,6016175500
00023668400101,D021609489358,D02160948,20150608135458,6107422418
00023668457901,D004719687172,D00471968,20150608135640,6100439132
00023668851801,4089771406,I22114577,20150608141433,2214456603
00023668867701,1097223690,C23934507,20150608140448,6107463339
[loguser@svcpreapp01 cut]$


以下部分为我在网上看到的一些总结,附在这里补充说明,主要是想强调单引号和双引号的区别:

Sed里使用变量的问题,网上有人总结了四种方案:

1. eval sed 's/$a/$b/' filename
2. sed "s/$a/$b/" filename
3. .sed 's/'$a'/'$b'/' filename
4. .sed s/$a/$b/ filename
我比较喜欢第二种,也就是:Sed后面的表达式一般用单引号引起来('),当需要使用变量时就换用双引号(")。

关于单双引号的区别:

单引号:shell处理命令时,对其中的内容不做任何处理。即此时是引号内的内容是sed命令所定义的格式。

双引号:shell处理命令时,要对其中的内容进行算术扩展。如果想让shell扩展后得到sed命令所要的格式,使用命令:sed
-n"/\\\\$/p" haha,扩展后得到的结果即\\$.

3.小结

总结一下,其实这里总共使用了三行命令就解决了问题,而且处理速度也比较快:

[loguser@svcpreapp01 cut]$ cut -d '$' -f 3,5,6,7,8 source.txt > result.txt
[loguser@svcpreapp01 cut]$ sed -i "s/[- :]//g" result.txt
[loguser@svcpreapp01 cut]$ sed -i 's/\$/,/g' result.txt
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: