Awk在“文件”列周围添加引号

Awk在“文件”列周围添加引号,awk,Awk,我正在处理一个以制表符分隔的文件,希望在列#1周围添加引号,如果字符串中有引号,还可以添加额外的引号(作为转义) 以下是文件的标题: auto_type compact 323 auto_type truck 219 auto_type truck 5" 25 预期结果: auto_type "compact" 323 auto_type "truck" 219 auto_type "truck 5"" 25 以下是我的初步尝试,至少在专栏周围添加引号: aw

我正在处理一个以制表符分隔的文件,希望在列#1周围添加引号,如果字符串中有引号,还可以添加额外的引号(作为转义)

以下是文件的标题:

auto_type  compact   323
auto_type  truck   219
auto_type  truck 5"  25
预期结果:

auto_type  "compact"   323
auto_type  "truck"   219
auto_type  "truck 5""  25
以下是我的初步尝试,至少在专栏周围添加引号:

awk -F, '{print gsub("\"","\"\"",$2)}' OFS=, vehicle_file.txt
  • 首先将所有的
    FS
    替换为
    “FS
  • 然后将第一个
    “FS
    替换为
    FS”
  • 首先将所有的
    FS
    替换为
    “FS
  • 然后将第一个
    “FS
    替换为
    FS”

您想要的输出是错误的,因为它用不匹配的双引号离开了第二个字段,应该是:

$ awk 'BEGIN{FS=OFS="\t"} {gsub(/"/,"\"\"",$2); $2="\"" $2 "\""} 1' file
auto_type       "compact"       323
auto_type       "truck" 219
auto_type       "truck 5"""     25

您想要的输出是错误的,因为它用不匹配的双引号离开了第二个字段,应该是:

$ awk 'BEGIN{FS=OFS="\t"} {gsub(/"/,"\"\"",$2); $2="\"" $2 "\""} 1' file
auto_type       "compact"       323
auto_type       "truck" 219
auto_type       "truck 5"""     25

如果需要将数据中已有的引号加倍,请在字段周围添加引号之前进行此操作。因此:

$ awk -F'\t' 'BEGIN { OFS=FS } { gsub(/"/, "\"\"", $2); $2 = "\"" $2 "\""; print }' data |
> pr -e16 -l1 -t
auto_type       "compact"       323
auto_type       "truck"         219
auto_type       "truck 5"""     25
$
(由于使用了
-e16
,因此
pr
命令将制表符扩展到16个空格;它使制表符易于查看并对齐数据。)

如果需要问题中显示的输出,请省略
gsub

$ awk -F'\t' 'BEGIN { OFS=FS } { $2 = "\"" $2 "\""; print }' data | pr -l1 -t -e16
auto_type       "compact"       323
auto_type       "truck"         219
auto_type       "truck 5""      25
$

但是,对于我所知道的任何CSV阅读器来说,此输出都不是可用的数据文件。

如果需要将数据中已有的引号加倍,请在字段周围添加引号之前进行此操作。因此:

$ awk -F'\t' 'BEGIN { OFS=FS } { gsub(/"/, "\"\"", $2); $2 = "\"" $2 "\""; print }' data |
> pr -e16 -l1 -t
auto_type       "compact"       323
auto_type       "truck"         219
auto_type       "truck 5"""     25
$
awk '{sub($2, "\"&\"")sub(/truck\42 5/,"truck 5\42")}1' file

auto_type  "compact"   323
auto_type  "truck"   219
auto_type  "truck 5""  25
(由于使用了
-e16
,因此
pr
命令将制表符扩展到16个空格;它使制表符易于查看并对齐数据。)

如果需要问题中显示的输出,请省略
gsub

$ awk -F'\t' 'BEGIN { OFS=FS } { $2 = "\"" $2 "\""; print }' data | pr -l1 -t -e16
auto_type       "compact"       323
auto_type       "truck"         219
auto_type       "truck 5""      25
$

但是,对于我所知道的任何CSV阅读器来说,此输出都不是可用的数据文件。

为什么需要此输出?对我来说,您所期望的输出看起来并不是一个改进,事实上似乎模棱两可。有一种CSV方言,它允许通过将文本双引号加倍嵌入双引号字段中,但在这里,您也没有这样做(如果您的值中没有制表符,为什么您一开始就需要这样做呢?)?通常,您需要
“truck 5”“”
(三个连续的双引号)来指示双引号是数据的一部分。如果忽略数据中有双引号这一事实,你所说的你想要的和你得到的是一样的。我知道连续引号很奇怪,但它是根据数据加载的要求而需要的。你为什么想要这样?对我来说,您所期望的输出看起来并不是一个改进,事实上似乎模棱两可。有一种CSV方言,它允许通过将文本双引号加倍嵌入双引号字段中,但在这里,您也没有这样做(如果您的值中没有制表符,为什么您一开始就需要这样做呢?)?通常,您需要
“truck 5”“”
(三个连续的双引号)来指示双引号是数据的一部分。如果忽略数据中有一个双引号这一事实,您所说的您想要的与您得到的是一样的。我知道连续引号很奇怪,但它是根据数据加载的要求而需要的。AWK解释
'\t'
在命令行上分配给变量时(包括当使用
-F
设置
FS
作为制表符时,不需要bashism
-F$'\t'
或literal
-F'•'
,只要
-F'\t'
就可以了。@EdMorton:这似乎对BSD(Mac OS X)都适用和GNU版本的
sed
,所以我更新了我的答案-谢谢。我认为POSIX规范在这一点上有点含糊不清;它肯定讨论了在某些上下文中表示选项卡的
\t
,因此在这里应用它也是一致的(并且简化了脚本编写)是的,如果你不想让它被解释为一个标签(并且假设你不能仅仅添加一个额外的转义),你实际上必须跳过一些障碍,例如,
FS='\t'awk'BEGIN{FS=ENVIRON[“FS”];printf“\n”,FS}
awk'BEGIN{FS=ARGV[1];ARGV[1]=”;printf“\n”,FS}''\t'。基本上,awk在命令行变量设置中解释反斜杠,就像默认情况下shell的
read
一样。awk在命令行上分配给变量时解释
'\t'
(包括使用
-F
设置
FS
时)作为制表符,不需要bashism
-F$'\t'
或literal
-F'•'
,只需要
-F'\t'
就可以了。@EdMorton:这似乎对BSD(Mac OS X)都有效和GNU版本的
sed
,所以我更新了我的答案-谢谢。我认为POSIX规范在这一点上有点含糊不清;它肯定讨论了在某些上下文中表示选项卡的
\t
,因此在这里应用它也是一致的(并且简化了脚本编写)是的,如果你不想让它被解释为一个标签(并且假设你不能仅仅添加一个额外的转义),你实际上必须跳过一些障碍,例如,
FS='\t'awk'BEGIN{FS=ENVIRON[“FS”];printf“\n”,FS}
awk'BEGIN{FS=ARGV[1];ARGV[1]=”;printf“\n”,FS}''\t'。基本上,awk在命令行变量设置中解释反斜杠,就像默认情况下shell的
read
一样。
awk '{sub($2, "\"&\"")sub(/truck\42 5/,"truck 5\42")}1' file

auto_type  "compact"   323
auto_type  "truck"   219
auto_type  "truck 5""  25