awk中$ 0 = $ 0的含义是什么?

时间:2017-01-30 09:54:47

标签: awk

在浏览一段代码时,我看到了以下命令:

grep "r" temp | awk '{FS=","; $0=$0} { print $1,$3}'

临时文件包含如下模式:

 1. r,1,5
 2. r,4,5
 3. ...

我无法理解语句$0=$0在awk命令中的含义。

任何人都可以解释它是什么意思吗?

4 个答案:

答案 0 :(得分:3)

$0 = $0最常用于重建已修改条目的字段分离评估。例如:在$ 0 = $ 0之后添加一个字段将改变$ NF,它保持原始状态(在该行的入口处)。

在这种情况下,将字段分隔符的每一行更改为,请参阅下面的@EdMorton注释以获取警示)使用当前FS重新分析该行info awk -F ',' { print $1 "," $3 }'更好地编码同一个想法的信息,在开始所有行时采用字段分隔符(在这种情况下,如果在通过前一行内容的示例处理depernding期间修改了分隔符,则可能会有所不同)< / p>

例如:

echo "foo;bar" | awk '{print NF}{FS=";"; print NF}{$0=$0;print NF}'
1
1
2

基于@EdMorton评论和相关帖子(What is the meaning of $0 = $0 in Awk

echo "a-b-c" |\
awk ' BEGIN{ FS="-+"; OFS="-"}
   function p(Ref) { printf "%12s) NF=%d $0=%s, $2=%s\n", Ref,NF,$0,$2 }
   {
   p("Org")
   $2="-"; p( "S2=-")
   $1=$1 ; p( "$1=$1")
   $2=$2 ; p( "$2=$2")
   $0=$0 ; p( "$0=$0")
   $2=$2 ; p( "$2=$2")
   $3=$3 ; p( "$3=$3")
   $1=$1 ; p( "$1=$1")
   } '

  Org) NF=3 $0=a-b-c, $2=b
 S2=-) NF=3 $0=a---c, $2=-
$1=$1) NF=3 $0=a---c, $2=-
$2=$2) NF=3 $0=a---c, $2=-
$0=$0) NF=2 $0=a---c, $2=c
$2=$2) NF=2 $0=a-c, $2=c
$3=$3) NF=3 $0=a-c-, $2=c
$1=$1) NF=3 $0=a-c-, $2=c

答案 1 :(得分:3)

当您执行$1=$1(或对字段的任何其他分配)时,它会导致记录重新编译,其中每个FS替换为OFS重建$ 0,但它不会更改NF或以任何其他方式重新评估记录。 / p>

当你执行$0=$0时,它会导致字段拆分,其中NF,$ 1,$ 2等根据FS的当前值重新填充,但它不会将FS更改为OFS或以任何其他方式修改$ 0。

查找

$ echo 'a-b-c' |
    awk -F'-+' -v OFS='-' '
        function p() { printf "%d) %d: $0=%s, $2=%s\n", ++c,NF,$0,$2 }
        { p(); $2=""; p(); $1=$1; p(); $0=$0; p(); $1=$1; p() }
    '
1) 3: $0=a-b-c, $2=b
2) 3: $0=a--c, $2=
3) 3: $0=a--c, $2=
4) 2: $0=a--c, $2=c
5) 2: $0=a-c, $2=c

请注意,即使将$ 2设置为null也会导致连续2次-,而-+的FS意味着2 - s是单个分隔符,但它们不是如此处理,直到$0=$0导致记录被重新拆分为字段,如输出步骤4所示。

您拥有的代码:

awk '{FS=","; $0=$0}'

正在使用$0=$0作为一个解决这个问题的事实,即在第一条记录被读取并分成字段之后它才设置FS:

$ printf 'a,b\nc,d\n' | awk '{print NF, $1}'
1 a,b
1 c,d

$ printf 'a,b\nc,d\n' | awk '{FS=","; print NF, $1}'
1 a,b
2 c

$ printf 'a,b\nc,d\n' | awk '{FS=","; $0=$0; print NF, $1}'
2 a
2 c

当然,正确的解决方案是简单地设置FS BEFORE读取第一条记录:

$ printf 'a,b\nc,d\n' | awk -F, '{print NF, $1}'
2 a
2 c

要清楚 - 将任何值分配给$ 0会导致字段拆分,它不会导致记录重新编译,同时将任何值分配给任何字段($ 1等)会导致记录重新编译但不会进行字段拆分:

$ echo 'a-b-c' | awk -F'-+' -v OFS='#' '{$2=$2}1'
a#b#c
$ echo 'a-b-c' | awk -F'-+' -v OFS='#' '{$0=$0}1'
a-b-c

答案 2 :(得分:1)

$0=$0用于重新评估字段

例如

akshay@db-3325:~$ cat <<EOF | awk '/:/{FS=":"}/\|/{FS="|"}{print $2}'
1:2
2|3
EOF


# Same with $0=$0, it will force awk to have the $0 reevaluated

akshay@db-3325:~$ cat <<EOF | awk '/:/{FS=":"}/\|/{FS="|"}{$0=$0;print $2}'
1:2
2|3
EOF
2
3

# NF - gives you the total number of fields in a record
akshay@db-3325:~$ cat <<EOF | awk '/:/{FS=":"}/\|/{FS="|"}{print NF}'
1:2
2|3
EOF

1
1

# When we Force to re-evaluate the fields, we get correct 2 fields
akshay@db-3325:~$ cat <<EOF | awk '/:/{FS=":"}/\|/{FS="|"}{$0=$0; print NF}'
1:2
2|3
EOF

2
2

答案 3 :(得分:0)

>>> echo 'a-b-c' | awk -F'-+' -v OFS='#' '{$2=$2}1' 
>>> a#b#c

这可以稍微简化为

mawk 'BEGIN { FS="[-]+"; OFS = "#"; } ($2=$2)'

Rationale是随后进行的布尔测试,将在分配后评估为true,因此它本身足以重新生成OFS中的字段并进行打印。