awk 字段分隔符更改后重新评估记录中的字段

LD9*_*D99 5 macos awk

(这是我在这里的第一篇文章,所以如果我问错了问题,请原谅我。)

我正在awk我的 OSX Maverick 上学习。我正在awk 上浏览本教程

我正在尝试在该教程中重现类似于 awk_example4a.awk 的内容。

所以我想出了这个 awk 程序/脚本/参数(不知道你叫它什么??):

BEGIN { i=1 }
{
    print "Line " i;
    print "$1 is " $1,"\n$2 is " $2, "\n$3 is " $3;
    FS=":";
    $0=$0;
    print "With the new FS - line " i;
    print "$1 is " $1,"\n$2 is " $2, "\n$3 is " $3;
    FS=" ";
    i++;
}
Run Code Online (Sandbox Code Playgroud)

输入文件如下所示:

A1 B1:B2 C2
A1:A2 B2:B3 C3
Run Code Online (Sandbox Code Playgroud)

我想要做的是首先使用默认值FS(空格)处理每一行/记录,然后使用新的FS(“:”)重新处理相同的行/记录,然后FS在转到下一条记录之前恢复默认值。

根据教程,$0=$0应该awk使用新的字段分隔符重新评估字段,因此应该给我一个看起来像这样的输出:

Line 1
$1 is A1 
$2 is B1:B2 
$3 is C2
With the new FS - line 1
$1 is A1 B1
$2 is B2 C2
$3 is
Line 2
$1 is A1:A2 
$2 is B2:B3 
$3 is C3
With the new FS - line 2
$1 is A1
$2 is A2 B2
$3 is B3 C3
Run Code Online (Sandbox Code Playgroud)

但相反,我得到:

Line 1
$1 is A1 
$2 is B1:B2 
$3 is C2
With the new FS - the line 1
$1 is A1 
$2 is B1:B2 
$3 is C2
Line 2
$1 is A1:A2 
$2 is B2:B3 
$3 is C3
With the new FS - the line 2
$1 is A1:A2 
$2 is B2:B3 
$3 is C3
Run Code Online (Sandbox Code Playgroud)

即字段FS在更改后没有被重新评估。

因此,如果$0=$0不起作用(并且也不起作用$1=$1; $2=$2),我如何让 awk 使用不同的 重新评估同一行FS

谢谢你。

mkl*_*nt0 3

TL; 博士:

FreeBSD/OS X在当前记录完成处理之前awk不会对FS(字段分隔符)应用更改- 这种行为实际上是POSIX 规定的(见下文)。

解决方法不要更改FS并使用函数split()

{
    print "Line " ++i
    print "$1 is " $1 "\n$2 is " $2 "\n$3 is " $3
    split($0, flds, ":")   # split current line by ':' into array `flds`
    print "With the new FS - line " i
    print "field1 is " flds[1] "\nfield2 is " flds[2] "\nfield3 is " flds[3]
}
Run Code Online (Sandbox Code Playgroud)
  • 请注意如何BEGIN通过依赖0数字上下文中默认的未初始化变量来消除该块。
  • 这些,实例已从print语句中删除,因为每个实例都会插入一个空格(输出字段分隔符的默认值OFS),在本例中不需要。
  • 鉴于语句是用换行符分隔的,;因此不需要终止它们。

请继续阅读有趣的多平台兼容性详细信息。


POSIX规范。对于awk各州(强调我的):

在评估对记录中字段的第一次引用之前,该记录应
根据正则表达式中的规则拆分为字段,
**使用读取记录时当前的 FS 值**。

关于为$0特定字段分配新值,同一来源指出:

符号 $0 指的是整个记录;设置任何其他字段原因
重新评估为0美元。分配给 $0 将重置所有其他的值
字段和 NF 内置变量。

换句话说:鉴于重新分配情况没有另外说明,这是对FSPOSIX 规范中给定值范围的唯一引用。要求它对于给定的输入记录是恒定的肯定存在歧义,如果规范肯定会有所帮助。解决了这个问题 - 也就是说,保守且因此更安全的解释是假设处理给定记录时恒定 FS

因此,FreeBSD/OS X 是awk模型公民,而GNUawkmawk提供了更大的灵活性,不遵守规则,甚至在重新分配到或任何特定字段时对当前FS记录应用更改$0

但请注意,GNU awk(从 v4.1.1 开始)甚至不会使用该--posix选项更改该行为,该选项的明确意图是导致符合 POSIX 的行为。如果我正在阅读 POSIX 规范。正确地(请告诉我是否是),这应该被视为一个错误