以编程方式更改字段分隔符(FS)并重新计算 gawk 中的当前记录?

以编程方式更改字段分隔符(FS)并重新计算 gawk 中的当前记录?

我只想更改特定记录的字段分隔符 ( FS),并且希望使用新的字段分隔符重新计算记录 ( $0)、字段 ( $N) 和字段数 ( )。NF但这似乎不起作用。

例子:这里我有一行被解释为由空格分隔的三个字段。如果我将字段分隔符更改为n并强制重新构建记录 ( $1 = $1),则记录保持不变,如打印所示$1

$ echo 'one two three' | awk '1 {FS="n" ; OFS=":" ; $1 = $1 ; print $1}'
> one

但我希望输出是:

> o

通过运行强制重新构成记录的技巧$1 = $1取自呆呆手册。所以我希望它能起作用。我不确定可能是什么问题:

FS尝试简单地通过设置和来更改记录中的字段分隔符OFS,然后期望一个普通的printprint $0打印修改后的记录,这是一个常见的错误。

但这不起作用,因为没有采取任何措施来更改记录本身。相反,您必须强制重建记录,通常使用诸如$1 = $1[...]

(我使用的是 GNU Awk 5.2.2)

答案1

关于

我只想更改特定记录的字段分隔符 (FS)

split()如果您使用该记录,您的代码可能会更清晰/更简单。

您混淆了 2 个概念 - 重建 $0 和重新分割 $0。

重建 $0:当您修改或以其他方式为字段赋值时,将从字段中重建 $0,用 OFS 替换每个 FS,例如

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $1 = $1 ; print; for (i=1; i<=NF; i++) print i, $i}'
one:two:three
1:one
2:two
3:three

重新分配 0 美元:当您修改或以其他方式为 $0 赋值时(除了由于更改字段而重建它的结果),$0 将使用现有的 FS 值重新分割为字段,例如

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $0 = $0 ; print; for (i=1; i<=NF; i++) print i, $i}'
one two three
1:o
2:e two three

现在尝试理解以下结果,看看您是否理解了上面的陈述:

重建然后重新分割:

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $1 = $1 ; $0 = $0; print; for (i=1; i<=NF; i++) print i, $i}'
one:two:three
1:o
2:e:two:three

重新分割然后重建:

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $0 = $0; $1 = $1 ; print; for (i=1; i<=NF; i++) print i, $i}'
o:e two three
1:o
2:e two three

答案2

环顾引用的文字,我看到:

最后,有时awk使用字段 和 的当前值强制重建整个记录是很方便的OFS

稍后接着是:

$0和领域之间的关系也有另一面。任何分配都会$0导致使用以下命令将记录重新解析为字段当前的的价值FS

从前一句中没有提及FS而第二句中强调它来看,我认为预期的方式是:$0 = $0会导致字段被重新计算;其他的只会导致记录改变输出无论字段的值是什么,而不尝试解析它们:

% echo 'one two three' | awk '1 {FS="n" ; OFS=":" ; $0 = $0 ; print $1}'
o

% echo 'one two three' | awk '{FS="n" ; OFS=":" ; $1 = $1 ; print}'
one:two:three

请注意,我没有使用 GNU awk:

% awk --version
awk version 20200816

但我希望 GNU awk 也能如此。

相关内容