2017-09-27 37 views
-1

我正在使用awk脚本解析bash中的csv。价值观与报价在$ 2“awk中的CSV格式替换引号

"1";"2";"3"

里面像

"1";"2"2";"3",我需要翻译成"1";"22";"3"

如何删除这些值有时候,我也没能逃脱引号”?首先我尝试检查$ 2,如果它里面有引号,但我卡住了。如果我使用gsub,它会从$ 2中删除所有报价,我会得到"1";22;"3"。我想过在gensub中使用gsub,但没有找到如何将函数传递给第二个参数的gensub。

cat test | awk 'BEGIN {OFS=FS=";"} \ {if ($2 ~ /^\".*.[\"].*\"$/) {$2 = "need help here")} \ print}'

**************** UPDATE ****************

也许有另一种方法对此。 awk中是否有任何特殊选项不仅设置了分隔符,而且还为分隔值设置了引号?这将是真棒,如果$ 1等不能作为“价值”,但作为价值本身,引号里的

+4

修复CSV生成器代码,使其不会生成格式不正确的CSV数据。踢,尖叫,叫喊,霍勒 - 在紧急情况下,提供给他们修复它 - 但做一些事情,以便修复拙劣的文件是没有必要的。显然,在短期内(一次性),你必须破解数据,但你不应该这样做,而且任何超过一次性的内容都是不可接受的。如果报价是嵌入式的,它们应该加倍:'“1”;“2”“2”;“3”'是有效的CSV,其中中间字段的值为'2“2'当未加引号时 –

+0

@JonathanLeffler谢谢但abnf说这个值是'word','word'可以包含'DQUOTE',所以我唯一能做的就是把引号改成“to”或者其他的东西,但是这会给我带来很大的痛苦,因为我需要重新配置我的生产环境,这并不容易。所以首先我需要考虑临时解决方法。 – ky4k0b

+1

你指的是哪个ABNF? –

回答

1

快速和肮脏的处理:使用GSUB并放回外报价:

$ echo '"1";"2"2";"3"' | awk -v q='"' 'BEGIN {FS=OFS=";"} {gsub(q,"",$2); $2 = q $2 q; print}' 
"1";"22";"3" 
+0

这很简单,唯一的警告是如果输入包含格式正确的字段,双引号,这会丢失这些信息。即“1”;“2”“2”;“”“3”“”'是有效的CSV;第二个字段数据包含'2“2',当没有引用时,第三个字段数据包含'”3“',但脚本会丢失这些引号。注意,CSV处理完全是棘手的东西(你也会遇到在第二个数据字段中包含分号的“4”;“5; 6”;“7”''的问题。 ) –

+0

非常好的观点,@JonathanLeffler。事实上,OP说“有时我没有逃脱引号”,这让人怀疑有时候OP是否已经逃脱了引号!如果是这样,一个更强大的解决方案将更多 – jas

0

下面的代码片段是一个潜在的答案。 awk声明使用RS代替FS,因此每个部分(如"1""2"2")都是分开打印的。然后tr命令删除所有引号。接下来,sed命令将引号添加回整个字段。最后,paste命令返回分号。

echo '"1";"2"2";"3"' | awk 'BEGIN{RS=";"}{print $1}' | tr -d '"' | sed -r 's|(.*)|"\1"|' | paste -sd ";" 
+0

当CSV文件中有多行时,这是如何工作的?我知道这个问题只显示一行,但是这是一个合理的猜测,即每个文件有多行。 –

0

删除所有领域点缀“的:

awk 'BEGIN{FS=OFS="\";\""} 
    { for (i=1;i<=NF;i++) 
      gsub(/"/,"",$i); 
     printf "\"%s\"\n", $0 
    }' input.txt 
与输入

所以:

$ cat input.txt 
"1";"2"2";"3" 
"1";"1"234"567""8";"1"2"3"4"5""" 

你会得到:

$ awk 'BEGIN{FS=OFS="\";\""}{for (i=1;i<=NF;i++) gsub(/"/,"",$i); printf "\"%s\"\n", $0 }' input.txt 
"1";"22";"3" 
"1";"12345678";"12345" 

真的要只需2美元?

awk 'BEGIN{FS=OFS="\";\""}{gsub(/"/,"",$2); printf "\"%s\"\n", $0}' input.txt 
""1";"22";"3"" 
""1";"12345678";"1"2"3"4"5"""" 
1
echo '"1";"2"2";"3"'| awk '{sub(/2"2/,"22")}1' 

"1";"22";"3" 
+0

有趣的答案:) – Styx

+0

haha​​ha ,这是一个很好的:) – ky4k0b

0

这应该妥善处理正确地转义报价,以及畸形的孤报价。我认为每场应该被引用

echo '"1";"2"2";"3""4"' | awk -F';' -v OFS=';' '{ 
    for (i=1; i<=NF; i++) { 
     sub(/^"/,"",$i) 
     sub(/"$/,"",$i) 
     gsub(/""/,SUBSEP,$i) 
     gsub(/"/,"",$i) 
     gsub(SUBSEP,"\"\"",$i) 
     $i = "\"" $i "\"" 
    } 
    print 
}' 
"1";"22";"3""4" 

注意,将打破"1";"2;3"数据

0

如果输入CAN领域内包含;当时的你的输入是模糊的,因为没有办法告诉如果"foo";"bar"是2个单独的字段或单个字段,因此无法解析。

如果你的输入不能包含字段内;当时的周围场的双引号不是必需的,所有你需要的是:

$ awk 'BEGIN{FS="\";\""; OFS=";"} {gsub(/"/,""); $1=$1} 1' file 
1;22;3 

,或者如果你觉得行情是相当:

$ awk 'BEGIN{FS=";"; OFS="\";\""} {gsub(/"/,""); $1="\""$1; $NF=$NF"\""} 1' file 
"1";"22";"3"