有许多使用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
$ 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结束从命令行前面开始的引号"
是语法,用于开始一个新的(双引号)引用上下文。'
在该上下文中是字面的。"
结束了从第三个字符开始的双引号上下文'
是语法,恢复以字符2结尾的单引号上下文"
是字面意思,传递给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
是换行符,并且 - 与我们的点相关 - \'
是单引号。
这在脚本中更容易,因为您不需要担心封闭的引号:
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
只需在需要单引号的地方使用八进制转义序列\047
:
awk 'BEGIN{FS=OFS=","} { $9= "\047" $9 "\047"; print }'
这避免了引用的任何复杂性以及其他方法带来的任何意外。
使用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