使用sed或awk拆分数据

时间:2013-12-16 12:23:21

标签: regex bash shell sed awk

我有很多数据我想用CSV分割。我的源数据具有以下格式:

* USER 'field1' 'mail1@domain.com' 'field3'
* USER 'field1' 'mail2@domain.com' 'field3'
* USER 'field1' 'mail3@domain.com' 'field3'

这就是我想要输出的内容:

field1;mail1@domain.com;field3
field1;mail2@domain.com;field3
field1;mail3@domain.com;field3

规则

    必须明显剥离行开头的
  1. * USER;
  2. field1field3可以是电子邮件地址,也可以包含';
  3. field1可能为空''
  4. 第二个字段始终是电子邮件地址;
  5. 每个字段在字段本身的开头和结尾都有'
  6. 我的想法是剥离* USERsed -e 's/^* USER //'可能是一个起点),然后在“中心”字段中“找到”邮件,然后将左侧和右侧捕获为两个瓦尔。最后一件事应该是在变量上删除开始和结束'。 不幸的是,我没有这个级别的sed或awk知识。关于如何实现这一点的任何想法?


    这是一个例子

    * USER '' 'alberto.cordini@generaligroup.com' 'CORDINI ALBERTO'
    * USER 'moglie delmonte daniele' 'anna.borghi@rpos.com' 'Anna Borghi'
    * USER '' 'annamaria.cravero@generaligroup.com' 'CRAVERO ANNA MARIA'
    * USER '' 'patrizia.dagostino@generaligroup.com' 'D'AGOSTINO PATRIZIA'
    * USER '' 'piero.depra@generaligroup.com' 'DE PRA' PIERO'
    * USER '' 'viviana.dingeo@generaligroup.com' 'D'INGEO VIVIANA'
    

5 个答案:

答案 0 :(得分:5)

更新:您可以将此awk用于提供的输入:

awk -F " '" '{gsub(/^ +| +$/, "", $3);
              s=sprintf("%s;%s;%s;", $2,$3,$4); gsub(/'"'"';/, ";", s); print s}' file
;alberto.cordini@generaligroup.com;CORDINI ALBERTO;
moglie delmonte daniele;anna.borghi@rpos.com;Anna Borghi;
;annamaria.cravero@generaligroup.com;CRAVERO ANNA MARIA;
;patrizia.dagostino@generaligroup.com;D'AGOSTINO PATRIZIA;
;piero.depra@generaligroup.com;DE PRA' PIERO;
;viviana.dingeo@generaligroup.com;D'INGEO VIVIANA;

答案 1 :(得分:4)

简单地:

$ awk '{print $2,$4,$6}' FS="'" OFS=";" file 
field1;mail1@domain.com;field3
field1;mail2@domain.com;field3
field1;mail3@domain.com;field3

答案 2 :(得分:0)

你可以使用sed和awk这样可以工作,但是和你一样,我不会经常使用那些(我发现它们很笨重)。如果您需要一个可以放在脚本中运行的解决方案,那么Ruby解决方案如何,我使用正则表达式,但您不必:

采样的data.txt

* USER 'field1' 'mail1@domain.com' 'field3'
* USER 'field1' 'mail2@domain.com' 'field3'
* USER 'field1' 'mail3@domain.com' 'field3'

parse.rb

#!/usr/bin/env ruby

$stdin.each_line do |e|
    matches = e.match /\*\ USER\ '([\w]*)'\ '([\w\@\.]*)'\ '([\w]*)'/
    if matches != nil
        puts "#{matches[1]};#{matches[2]};#{matches[3]}"
    end
end

从终端/命令行:

cat sample-data.txt | ruby parse.rb

P.S。对我来说,如果它是一次性的问题,我会在Windows中使用Notepad ++。我会打开文件,然后录制一个宏,并将宏播放到文件的末尾,完成。

答案 3 :(得分:0)

 sed "s/²/²S/g;s/\\'/²q/g;s/\*[[:blank:]]USER[[:blank:]]\{1,\}'\([^']*\)'[[:blank:]]*'\([^']*\)'[[:blank:]]*'\(.*\)'[[:blank:]]*$/\1;\2;\3/;s/²q/\\'/g;s/²S/²/g" YourFile.csv

假设内部没有'的字段1未被转义

答案 4 :(得分:0)

一个sed示例,它依赖于引号分隔字段之间存在单个空格的事实。如果情况并非如此,那么需要修改才能更加“灵活”。

为了避免shell引用 - 逃避这种丑陋的体验,我会将一个衬垫放入文件中。 -r使用扩展的regexp(避免引用())。 field1和field3中的单引号由regexp贪婪保留(吃掉所有东西,包括引号,直到最后一个引用:)

sed -r -f s.sed samp.csv

s.sed:

s/\* USER '(.*)' '([^']*)' '(.*)'/\1;\2;\3/