使用awk用单引号包装单个字段

时间:2016-07-19 14:03:45

标签: regex bash csv awk sed

有很多例子使用awk用双引号来包装字段。我没有成功地试图在postgresql中用数字加载csv文件的单引号括起来。

以下是我的一些尝试:

#!/usr/bin/awk -f
BEGIN { FS=OFS=","}

{
  for (i = 1; i <= NF; ++i)
    if($i == 9)
    {
        $i = "\'' $i \''"
    }

  print $0 >> "output.csv"
}

awk 'BEGIN { OFS=FS="," } { $9= ""'" $9 ""'"} 1' container.csv > output.csv

...也

awk -v q="'" 'BEGIN { FS="," } { sub($9, ""\'"&"\'"" );print}' container.csv > output.csv

4 个答案:

答案 0 :(得分:1)

$ awk 'BEGIN { FS = OFS = "," } { $9= "'"'"'" $9 "'"'"'"; print }' \
>    <<<one,two,three,four,five,six,seven,eight,nine,ten
one,two,three,four,five,six,seven,eight,'nine',ten

这里很棘手的事情是通过bash将引号引入awk - 如果你在单引号命令行参数中有一个引号,那么它将视为结束从'BEGIN开始的引用上下文,而不是作为要发送到awk的文字内容。

因此,"'"'"'"做了必要的诡计:

  • 第一个字符"是文字,传递给awk
  • 第二个字符'是语法,用于告诉shell结束从命令行前面开始的引号
  • 第三个字符"是句法字符,用于开始一个新的(双引号)引用上下文。
  • 第四个字符'在该上下文中是字面意思。
  • 第五个字符"结束从第三个字符开始的双引号上下文
  • 第六个字符'是句法,恢复以字符二结束的单引号上下文
  • 第七个字符"是字面意思,传递给awk。

因此,实际传递给awk以用作上述中的脚本的是:

BEGIN { FS = OFS = "," } { $9= "'" $9 "'"; print }

...如果您愿意,可以直接放入文件中;如果那个awk脚本有一个#!/usr/bin/awk -f shebang,它应该直接作为命令执行。

顺便说一下,如果你的shell是bash,那么有一个替代的引用上下文会使这个更糟糕:

$ awk $'BEGIN { FS = OFS = "," } { $9= "\'" $9 "\'"; print }'

$''内部,反斜杠转义符合荣誉 - \t是标签,\f是字段分隔符,\r是换行符,并且 - 与我们相关点 - \'是单引号。

答案 1 :(得分:1)

在脚本中这是很多,因为您不必担心封闭的引号:

BEGIN { FS = OFS = "," }

{ 
    $9 = "'" $9 "'"
    print
}

我不确定你的循环应该做什么!

使用Charles提供的输入进行测试:

$ cat file
one,two,three,four,five,six,seven,eight,nine,ten
$ awk -f script.awk file
one,two,three,four,five,six,seven,eight,'nine',ten

答案 2 :(得分:1)

只需在需要单引号的地方使用八进制转义序列\047

awk 'BEGIN{FS=OFS=","} { $9= "\047" $9 "\047"; print }'

这避免了引用的任何复杂性以及由其他方面产生的任何意外。

答案 3 :(得分:1)

使用sed

的解决方案
$ s='one,two,three,four,five,six,seven,eight,nine,ten'

$ # s///n means nth matching occurrence
$ echo "$s" | sed "s/[^,]*/'&'/9"
one,two,three,four,five,six,seven,eight,'nine',ten
$ # * used as quantifier so that it will work on empty fields too
$ echo 'a,c,,d' | sed "s/[^,]*/'&'/3"
a,c,'',d  

$ # or if hex escape sequences are allowed
$ # this is preferred as it avoids shell interpretation within double quotes
$ echo "$s" | sed 's/[^,]*/\x27&\x27/9'
one,two,three,four,five,six,seven,eight,'nine',ten