Awk里的域赋值操作和部分源码解析(二)

上一篇 / 下一篇  2011-08-08 00:26:11 / 个人分类:AWK学习

这个结果与下边等同:

  1. [root@rac_2 ~]# echo "1CA2CA3CA"|awk 'BEGIN{FS="A"}{FS="C";OFS="B";print $3}'             
  2. 3C  
 

 

 

=====================================================================================================

二:awk部分源码解析(结点树简介,及域模块)

 

man还是有些不够清晰的,或多或少会留下点疑问,应该会有人考虑到$0在分割之后存放成各个域,既然可以通过各个域拼接起来,为什么还要保存一份原先的串的样本?

比如怎么证明$0是独立于$1,$2,$3的存储存在?这样做又出于什么考虑?

再比如为什么在$1=$1后不是立即重构$0,而是在引用的时候才重构。

再比如对$0进行赋值后,是直接触发分割的,还是在引用域前才进行分隔。

 

没什么什么比查源码更能回答这些问题的了

 

通过查看awk的源码中的awk.h头文件可以了解到awk的源码的核心数据结构:结点(typedef struct  NODE)和结点树,awk代码里的各种元素都是以树和结点这种结构存在的,变量如FS/$0/$0是结点,操作符如“=赋值符等”也是结点,内置函数(builtin)也是结点,哈希数组也是结点。

awk是以节点(node 结构)树的形式保存各种变量和操作的,比如各变量,各{}操作块都是树的节点。awk通过调用awkgram.cyylex+yyparse二个函数,解析awk程序,并形成各种树,比较典型的,如主体程序有三颗数:

  1. /* A block of AWK code to be run before running the program */  
  2. NODE *begin_block = NULL;  
  3. /* The parse tree is stored here.  */  
  4. NODE *expression_value;  
  5. /* A block of AWK code to be run after the last input file */  
  6. NODE *end_block = NULL;  
 

 

程序块在解析形成树之后,由函数 执行Int interpret(register NODE *volatile tree)

begin模块跟end模块都执行一次

  1. if (begin_block != NULL) {  
  2.         in_begin_rule = TRUE;  
  3.         (void) interpret(begin_block);  
  4. }  
  5. if (end_block != NULL) {  
  6.         in_end_rule = TRUE;  
  7.         (void) interpret(end_block);  
  8. }  
 

而中间模块:expression_value 是在do_input里,一次读一一条记录执行一次的

  1. for (;;) {                                                                                 
  2.         rval2 = rval3 = -1;     /* for debugging */                                        
  3.         rval2 = interpret(expression_value);                                               
  4.         if (rval2 != 0)                                                                    
  5.                 rval3 = inrec(iop);                                                        
  6.         if (rval2 == 0 || rval3 != 0)                                                      
  7.                 break;                                                                     
  8. }   
 

 

然后回到正题:域模块源码:field.c,通过分析模块的数据结构和函数来了解模块设计,包括分隔符设计,记录分割,记录设置,域设置等

 

首先是数据结构:

  1. NODE **fields_arr;              /* array of pointers to the field nodes */  
 

fields_arr数组保存了所有域节点,$1,2...分别对应一样的下标fields_arr[1,2…]

C的数组索引是从0开始的,这里也不例外,

fields_arr[0]是用于保存完整记录的节点,保存记录值,即$0

 

 

 

然后是函数,我们关注函数的功能和调用。

 

NF相关函数:

 

NF(域数值)赋值函数:

  1. void set_NF()  
 

      直接更改NF值,域数组随NF长短做伸缩

       最后一句话:field0_valid = FALSE;涉及到记录重构,见rebuild_record()

 

记录层面的函数:赋值,重构,域分割等

 

记录重置函数:

<a href="http://blog.csdn.net/sosodream/article/details/6425192#" class="ViewSource" title="view plain" style="color: rgb(160, 160, 160); text-decoration: none; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-atta

TAG:

abinNO1的个人空间 引用 删除 abinNO1   /   2011-09-20 09:21:27
http://blog.csdn.net/sosodream/article/details/6425192
awk的域赋值与源码解析
abinNO1的个人空间 引用 删除 abinNO1   /   2011-09-20 09:20:29
http://bbs.chinaunix.net/thread-1942284-1-1.html
cpio详解
abinNO1的个人空间 引用 删除 abinNO1   /   2011-08-10 20:51:09
#!/bin/bash

awk 'NF{print $0}' renewlist.txt |awk '!a[$0]++'|awk -F/ '{print $NF}'|awk 'a[$0]++' > dud
while read b
do
        an=`grep $b renewlist.txt|wc -l`
        j=1
        while ((j<$an));do
        s1n=`grep $b renewlist.txt |sed -n ${j}p`
        echo "$s1n"
        j=`expr $j + 1`
        s2n=`grep $b renewlist.txt |sed -n ${j}p`
        echo "$s2n"
        s1f=`echo $s1n|awk -F/ '{print NF}'`
        s2f=`echo $s2n|awk -F/ '{print NF}'`
        while (($s1n>0&&$s2n>0));do
        str1
        done
        done
done < dud
/usr/local/USM/plugins/com.huawei.usmccm/webapps/WebRoot/WEB-INF/classes/com/huawei/usmccm/constant/Constants.class
/usr/local/USM/plugins/com.huawei.usmccm/webapps/WebRoot/WEB-INF/classes/com/huawei/usmccm/pso/constant/Constants.class
 

评分:0

我来说两句

Open Toolbar