在awk中设置输出字段分隔符

23
我正在尝试在我的awk脚本中使用这个语句(在一个包含单独代码的文件中,因此不是内联的),脚本名称:print-table.awk。
BEGIN {FS = "\t";OFS = "," ; print "about to open the file"}
{print $0}
END {print "about to close stream" }

并且通过从shell中执行它来运行

awk -f print-table.awk table

当表格是一个以制表符分隔的文件时, 我的目标是在外部函数中声明字段分隔符(FS)和输出字段分隔符(OFS),并且仅通过shell调用。

awk -f file input

没有在命令行中使用-F"\t"设置字段分隔符,也没有将其输出到sed语句中以用逗号替换制表符。你有什么建议吗?

3
你是不是只想用逗号替换制表符? tr \\t , < input - William Pursell
2个回答

29

您需要说服awk,让它相信某些事情已经改变,以便使用您的OFS重新格式化$0。以下方法可以工作,但可能有更符合惯用法的方法。

BEGIN {FS = "\t";OFS = "," ; print "about to open the file"}
{$1=$1}1
END {print "about to close stream" }

5
你应该像anubhava一样做 {$1=$1}1。如果第一个字段是0,则 $1=$1 会失败,它将不会被视为真并且不会被打印出来。 - Jotne
是的,我原本有anubhava写的代码,但后来为了简洁性而尝试进行“高尔夫”操作。NF=NF可以避免零问题,但仍然存在空字符串版本,所以我想更长的版本是正确的选择。 - Etan Reisner
嗨Etan,谢谢回复,但这是为什么呢?为什么我要更改一个字段或“伪造”以更改其中一个字段?我认为BEGIN例程的任务是初始化属性以应用于主例程,无论如何,我不明白为什么需要更改... - JBoy
3
因为若没有重建 $0 的内容,awk 不会根据 OFS 格式化 $0。除非你让 awk 意识到这一点,否则它会保持 $0 的内容不变,OFS 只用于生成的输出中。如果您阅读 awk 手册页的 Fields 部分中倒数第二段,您将看到对该概念的引用。 - Etan Reisner
@EtanReisner 你说的“仍然有空字符串版本”是什么意思? - jarno

10

您需要在awk中更改一个字段:

awk 'BEGIN {FS="\t";OFS=","; print "about to open the file"} {$1=$1}1' file

2
嘿,Anubhava,{$1=$1}后面的1代表什么意思?另外,你说“你需要更改一个字段”,但据我所知,“我通常使用bash”中的$1=$1并没有更改$1,而是重新分配了相同的值。 - JBoy
2
是的,我指的只是重新赋值。 $1=$1 不改变字段的值,但是强制使用提供的OFS作为逗号来重新格式化输入记录。此外,末尾的 1 也可以是任何其他非零值,基本上告诉awk打印输入记录。 - anubhava
@anubhava 1 什么情况下是必需的?例如,即使为空的字段也会在没有它的情况下打印: echo ",0,eh" | awk 'BEGIN {FS=",";OFS="--"} {$1=$1} {print $0}' - Simon A. Eugster
那个 awk 可以重写为:awk 'BEGIN {FS=",";OFS="--"} {$1=$1} 1 - anubhava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接