除了字符串列中的字符之外的分隔符替换

时间:2013-02-22 18:47:41

标签: regex shell unix awk

我有这种格式的3Gb文件:

...
201211 001093223359 "PLANO ESPECIAL" "PLANO NOVO"
201211 001199175239 "PLANO ESPECIAL" "PLANO NOVO"
201211 001292676219 "PLANO ESPECIAL" "PLANO NOVO"
...

我需要将其格式更改为下面的格式:

...
201211;001093223359;"PLANO ESPECIAL";"PLANO NOVO"
201211;001199175239;"PLANO ESPECIAL";"PLANO NOVO"
201211;001292676219;"PLANO ESPECIAL";"PLANO NOVO"
...

前5行与输入文件中的完全相同:

"Mes_Referencia" "Num_Telefone" "Dsc_Plano_Tarifario" "Grupo Plano"
201211 2183223350 "INFINITY PR?" "PLANO INFINITY"
201211 2169175232 "INFINITY PR?" "PLANO INFINITY"
201211 2182676211 "INFINITY PR?" "PLANO INFINITY"
201211 2281699337 "INFINITY PR?" "PLANO INFINITY"
201211 2179173096 "INFINITY PR?" "PLANO INFINITY"

评论:?在“INFINITY PR?”是因为它是“É”(它是葡萄牙语 - 巴西)。

如何将de delimiter“”(空格)更改为“;”不改变最后两列中字符串中的空格?

提前致谢!

5 个答案:

答案 0 :(得分:2)

通过以下命令过滤文件:

sed -E -e 's/ ([^ "]*|"[^"]*")/;\1/g'

此命令假定未引用第一列。如果可能,正则表达式会稍微复杂一些。

示例输入:

201211 2183223350 "INFINITY PRE" "PLANO INFINITY"
201211 2182067250 "ASS. PLANO NOSSO MODO-G11" "OUTROS"
201211 8199712912 "TIM LIBERTY CONTROLE" "PLANO LIBERTY"

示例输出:

201211;2183223350;"INFINITY PRE";"PLANO INFINITY"
201211;2182067250;"ASS. PLANO NOSSO MODO-G11";"OUTROS"
201211;8199712912;"TIM LIBERTY CONTROLE";"PLANO LIBERTY"

答案 1 :(得分:2)

无论您的文件中有多少行,它都可以正常工作,因为它只是一次处理一行:

awk 'BEGIN{FS=OFS="\""} {for (i=1;i<NF;i+=2) gsub(/ /,";",$i)} 1' file

e.g:

$ cat file
"Mes_Referencia" "Num_Telefone" "Dsc_Plano_Tarifario" "Grupo Plano"
201211 2183223350 "INFINITY PR?" "PLANO INFINITY"
201211 2169175232 "INFINITY PR?" "PLANO INFINITY"
201211 2182676211 "INFINITY PR?" "PLANO INFINITY"
201211 2281699337 "INFINITY PR?" "PLANO INFINITY"
201211 2179173096 "INFINITY PR?" "PLANO INFINITY"
$
$ awk 'BEGIN{FS=OFS="\""} {for (i=1;i<NF;i+=2) gsub(/ /,";",$i)} 1' file
"Mes_Referencia";"Num_Telefone";"Dsc_Plano_Tarifario";"Grupo Plano"
201211;2183223350;"INFINITY PR?";"PLANO INFINITY"
201211;2169175232;"INFINITY PR?";"PLANO INFINITY"
201211;2182676211;"INFINITY PR?";"PLANO INFINITY"
201211;2281699337;"INFINITY PR?";"PLANO INFINITY"
201211;2179173096;"INFINITY PR?";"PLANO INFINITY"

答案 2 :(得分:1)

如何用;替换前2个空格,用" "替换每个";"

$ sed 's/ /;/;s/ /;/;s/" "/";"/g' file
201211;001093223359;"PLANO ESPECIAL";"PLANO NOVO"
201211;001199175239;"PLANO ESPECIAL";"PLANO NOVO"
201211;001292676219;"PLANO ESPECIAL";"PLANO NOVO"

使用-i开关进行内联更改。

使用30000003行文件的一些时间:

$ time sed 's/ /;/;s/ /;/;s/" "/";"/g' f1 > /dev/null

real    1m58.305s
user    1m54.811s
sys 0m1.488s

$ time awk 'BEGIN{FS=OFS="\""} {for (i=1;i<NF;i+=2) gsub(/ /,",",$i)} 1' f1 > /dev/null

real    1m46.916s
user    1m45.831s
sys 0m0.852s


$ time sed -E -e 's/ ([^ "]*|"[^"]*")/;\1/g' f1 > /dev/null

real    20m52.172s
user    20m47.430s
sys 0m2.536s

即。 BIG 对gready运算符和反向引用的惩罚!

答案 3 :(得分:0)

awk应该可以解决问题。

awk -v OFS=";" '{print $1,$2,$3" "$4,$5" "$6}'

答案 4 :(得分:0)

尝试:

awk 'NR%2{gsub(/[ \t]+/,";")}1' RS=\" ORS=\" file