Regex 使用sed或awk分割数据
我有很多数据要在CSV中拆分。我的源数据具有以下格式:Regex 使用sed或awk分割数据,regex,bash,shell,sed,awk,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@d
* 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
规则:
*行开头的用户
必须明显剥去李>
field1
和field3
可以是电子邮件地址,也可以包含”
李>
字段1
可以为空'
”
*USER
(sed-e的/^*USER/'
可能是一个起点),然后在“中心”字段中“查找”邮件,然后将左侧和右侧分为两个变量。最后一件事应该是去掉vars上的开头和结尾“
。
不幸的是,我没有这个级别的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'
更新:您可以将此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;
简单地说:
$ awk '{print $2,$4,$6}' FS="'" OFS=";" file
field1;mail1@domain.com;field3
field1;mail2@domain.com;field3
field1;mail3@domain.com;field3
你可以使用sed和awk,这很管用,但像你一样,我不经常使用它们来记忆(我发现它们很笨重)。如果您需要一个可以放入脚本中随时运行的解决方案,那么Ruby解决方案如何?我使用正则表达式,但您不必: sample-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、 对我来说,如果这是一次性的问题,我会在Windows中使用记事本+。我会打开文件,然后录制一个宏,然后将宏播放到文件末尾,完成
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
假设在一个
sed
示例中,没有内部带有“
的字段1是/不是转义的,这取决于引号分隔的字段之间存在单个空格这一事实。如果情况并非如此,则需要修改以使其更加“灵活”
为了避免shell引用转义(这是一种丑陋的体验),我会将一行代码放入一个文件中-r使用扩展的regexp(避免引用()
s)。字段1和字段3中的单引号由regexp greediness保留(吃所有东西,包括引号,直到最后一个引号:)
s、 sed:
s/\* USER '(.*)' '([^']*)' '(.*)'/\1;\2;\3/
如果你能够添加一个小样本,包含你添加到帖子中的案例/规则,肯定会更容易提供帮助。我在下面发布了一个示例,为什么使用
'
而不是“
来包围可能包含'
的名称?…这是在自找麻烦。好吧,这只需稍作改动即可。FS=“\047”“
。有些系统不接受这一点。至少我的solaris boxI喜欢使用开头和结尾撇号作为FS。直到用户O'Hara使用他的真名(谷歌xkcd Johnny Tables提供了一个警示性的故事)为止。仍然得到我的选票…它没有像预期的那样工作。看看下面的例子,你在答案中看到的'D'INGEO VIVIANA'
应该是编辑的?它没有按预期工作。看下面的例子,我必须保存“字段内部(而不是外部)”哦,完美!还有一个问题:是否可以“修剪”电子邮件地址/$3?修剪的意思是修剪电子邮件字段中的空格?巧妙地使用“'”
分隔符。没问题!只是想给你一个选择。
s/\* USER '(.*)' '([^']*)' '(.*)'/\1;\2;\3/