awk的$1=$1与$0=$0  

2012-04-16 10:41:03|  分类: Editor |  标签:linux  awk   |字号 订阅

 
 
$1=$1 是用来激活$0的重新赋值,也就是说 字段$1...和字段数NF的改变会促使awk重新计算$0的值,通常是在改变OFS后而需要输出$0时这样做

    echo "A B C D" | awk '{OFS="|";print $0;$1=$1;print $0;}'
    A B C D
    A|B|C|D
   
    即使OFS放在BEGIN里,也没有用
    echo "A B C D" | awk 'BEGIN{OFS="|"}{print $0;$1=$1;print $0;}'
    A B C D
    A|B|C|D

   $0=$0 刚好相反, 修改$0的值可以促使awk重新计算字段$1...和字段数NF的的值,通常是在改变FS后而需要输出$1...或者NF时这样做

    echo "A|B|C|D" | awk '{FS="|";print $1,NF;$0=$0;print $1,NF}'
    A|B|C|D 1
    A 4
   
    不过把修改FS放在BEGIN里,就没必要$0=$0了
    echo "A|B|C|D" | awk 'BEGIN{FS="|"}{print $1,NF;$0=$0;print $1,NF}'
    A 4
    A 4
   
其实,在awk源码中.重新计算$0的值的函数名叫rebuild_record,重构记录的意思.默认情况下.这个函数是不可能执行的.因为$0是直接读入的.$1=$1等修改字段的行为会触发awk执行这个函数
重新计算$1...的值的函数名叫reset_record,重新分割记录到字段的意思.默认情况下.这个函数只在处理完当前行,读入下一行之前执行.中途是不会执行的.$0=$0等修改记录的行为会触发awk执行这个函数
通过在源码中添加一行标记重新编译awk.可以查看awk到底什么时候运行了这两个函数.

rebuild_record
  1. echo "A B C D" | awk '{print $0;OFS="|";print "OFS=\"|\"";print $0;print "$1=$1";$1=$1;print $0;}'
     
  2. -----------reset_record-----------             #读入行之前,执行reset_record,把$0拆分开赋值给$1...
     
  3. A B C D                                         #$0为读入的值
     
  4. OFS="|"                                        #改变OFS
     
  5. A B C D                                         #没有触发rebuild_record重构$0,$0仍为读入的值.
     
  6. $1=$1                                           #执行$1=$1,
     
  7. ----------rebuild_record------------            #awk不管$1是否真的改变,执行rebuild_record.
     
  8. A|B|C|D                                         #$0的值成为各个字段和ORS计算出的值

reset_record
  1. echo "A|B|C|D" | awk '{print $1,NF;print "FS=\"|\"";FS="|";print $1,NF;print "$0=$0";$0=$0;print $1,NF}'
     
  2. -----------reset_record-----------              #读入行之前,执行reset_record,把$0拆分开赋值给$1...
     
  3. A|B|C|D 1                                        #$1为刚才计算的值
     
  4. FS="|"                                             #改变FS
     
  5. A|B|C|D 1                                        #没有触发reset_record重构$1和NF,仍为第一次计算的值.
     
  6. $0=$0                                             #执行$0=$0
     
  7. -----------reset_record-----------              #awk不管$0是否真的改变,执行reset_re