//*******************************************************************
//在许多情况下我们需要穷举组合的算法,比如密码词典。
//这个算法的关键是密码下标进位的问题。
//另外本例子中的写文件语句效率比较低,为了降低算法复杂度没有优化。
//如果要提高写文件的效率,可以使用缓冲区,分批写入。
//*********************************************breath.cnpick.com*****
#define passwordmax 8 //将生成密码的最大长度

在文本处理的工作中,awk的数组是必不可少的工具,在这里,同样以总结经验和教训的方式和大家分享下我的一些学习心得,如有错误的地方,请大家指正和补充。

void createpassword()
{
char a[]=”0123456789abcdefghijklmnopqrstuvwxyz”; //可能的字符
long ndictcount=sizeof(a); //获得密码词典长度
char cpass[passwordmax+2]; //将生成的密码
long nminl=1,nmaxl=3; //本例中密码长度从1-3
long array[passwordmax]; //密码词典下标
assert(nminl<=nmaxl && nmaxl<=passwordmax);//容错保证
long nlength=nminl;
register long j,i=0;
bool bnext;
cstdiofile file;
file.open(“c:\dict.txt”,cfile::modecreate|cfile::modewrite);
while(nlength<=nmaxl)
{
for(i=0;i<passwordmax;i++)
array=0;
bnext=true;
while(bnext)
{
for(i=0;i<nlength;i++)
cpass
=a[array];
cpass
=’’;
file.writestring(cpass);
file.writestring(“n”);
for(j=nlength-1;j>=0;j–) //密码指针进位
{
array[j]++;
if(array[j]!=ndictcount-1)break;
else
{
array[j]=0;
if(j==0)bnext=false;
}
}
}
nlength++;
}
file.close();
}**

澳门新葡亰8455下载app ,awk的数组,一种关联数组(Associative
Arrays),下标可以是数字和字符串。因无需对数组名和元素提前声明,也无需指定元素个数
,所以awk的数组使用非常灵活。
首先介绍下几个awk数组相关的知识点:

<1>建立数组

  1.  
  2. array[index] =
    value :数组名array,下标index以及相应的值value。
  3.  

复制代码

<2>读取数组值

  1.  
  2. { for (item in
    array)  print array[item]} # 输出的顺序是随机的
  3. {for(i=1;i<=len;i++)  print
    array[i]} # Len 是数组的长度
  4.  

复制代码

<3>多维数组,array[index1,index2,……]:SUBSEP是数组下标分割符,默认为“34”。可以事先设定SUBSEP,也可以直接在SUBSEP的位置输入你要用的分隔符,如:

  1.  
  2. awk
    ‘BEGIN{SUBSEP=”:”;array[“a”,”b”]=1;for(i in array) print
    i}’
  3. a:b
  4. awk
    ‘BEGIN{array[“a””:””b”]=1;for(i in array) print i}’
  5. a:b
  6.  

复制代码

但,有些特殊情况需要避免,如:

  1.  
  2. awk ‘BEGIN{
  3. SUBSEP=”:”
  4. array[“a”,”b:c”]=1    
              # 下标为“a:b:c”
  5. array[“a:b”,”c”]=2    
              #下标同样是“a:b:c”
  6. for (i in array)
    print i,array[i]}’
  7. a:b:c 2          
                          #所以数组元素只有一个。
  8.  

复制代码

<4>删除数组或数组元素:
使用delete 函数

  1.  
  2. delete array       
                 #删除整个数组
  3. delete
    array[item]           # 删除某个数组元素(item)
  4.  

复制代码

<5>
排序:awk中的asort函数可以实现对数组的值进行排序,不过排序之后的数组下标改为从1到数组的长度。在gawk
3.1.2以后的版本还提供了一个asorti函数,这个函数不是依据关联数组的值,而是依据关联数组的下标排序,即asorti(array)以后,仍会用数字(1到数组长度)来作为下标,但是array的数组值变为排序后的原来的下标,除非你指定另一个参数如:asorti(a,b)。(非常感谢lionfun对asorti的指正和补充澳门新葡亰8455下载app 1

  1.  
  2. echo ‘aa
  3. bb
  4. aa
  5. bb
  6. cc’ |
  7. awk
    ‘{a[$0]++}END{l=asorti(a);for(i=1;i<=l;i++)print
    a[i]}’
  8. aa
  9. bb
  10. cc
  11.  
  12. echo ‘aa
  13. bb
  14. aa
  15. bb
  16. cc’ |
  17. awk
    ‘{a[$0]++}END{l=asorti(a,b);for(i=1;i<=l;i++)print
    b[i],a[b[i]]}’
  18. aa 2
  19. bb 2
  20. cc 1
  21.  

复制代码

下面说awk数组的实际应用。

1.  除去重复项,
这个不多说, 只给出代码:

  1.  
  2. awk ‘!a[$0]++’
    file(s)                   
  3. awk ‘!($0 in
    a){a[$0];print}’ file(s)    
  4.  

复制代码

另一种: 

2.
计算总数(sum),如:

  1.  
  2. awk  ‘{name[$0]+=$1};END{for(i
    in name) print  i, name[i]}’
  3.  
  4. 再举个例子:
  5.  
  6. echo “aaa 1
  7. aaa 1
  8. ccc 1
  9. aaa 1
  10. bbb 1
  11. ccc 1″ |awk
    ‘{a[$1]+=$2}END{for(i in a) print i,a[i]}’
  12. aaa 3
  13. bbb 1
  14. ccc 2
  15.  
  16.  
  17.  

复制代码

3.
查看文件差异。

  1.  
  2. cat file1
  3. aaa
  4. bbb
  5. ccc
  6. ddd
  7. cat file2
  8. aaa
  9. eee
  10. ddd
  11. fff
  12.  

复制代码

<1>  合并file1和file2,除去重复项:

  1.  
  2. awk
    ‘NR==FNR{a[$0]=1;print} 
     #读取file1,建立数组a,下标为$0,并赋值为1,然后打印
  3. NR>FNR{       
               #读取file2
  4. if(!(a[$0]))
    {print }      #如果file2
    的$0不存在于数组a中,即不存在于file1,则打印。
  5. }’ file1
    file2
  6. aaa
  7. bbb
  8. ccc
  9. ddd
  10. eee
  11. fff
  12.  

复制代码

<2>
提取文件1中有,但文件2中没有:

  1.  
  2. awk
    ‘NR==FNR{a[$0]=1}       
       #读取file2,建立数组a,下标为$0,并赋值为1
  3. NR>FNR{       
               #读取file1
  4. if(!(a[$0]))
    {print }      #如果file1
    的$0不存在于数组a中,即不存在于file2,则打印。
  5. }’ file2
    file1
  6. bbb
  7. ccc

复制代码

另:http://bbs.chinaunix.net/viewthr

&page=1#pid15547885 

4.  排序:

  1.  
  2. echo “a
  3. 1
  4. 0
  5. b
  6. 2
  7. 10
  8. 8
  9. 100″ |
  10. awk ‘{a[$0]=$0}
    #建立数组a,下标为$0,赋值也为$0
  11. END{
  12. len=asort(a)    
     #利用asort函数对数组a的值排序,同时获得数组长度len
  13. for(i=1;i<=len;i++)
    print i “t”a[i]  #打印
  14. }’
  15. 1       0
  16. 2       1
  17. 3       2
  18. 4       8
  19. 5       10
  20. 6       100
  21. 7       a
  22. 8       b

复制代码

5.  有序输出:采用(index
in
array)的方式打印数组值的顺序是随机的,如果要按原序输出,则可以使用下面的方法:

  1.  
  2. awk
    ‘{a[$1]=$2
  3. c[j++]=$1}
  4. END{
  5. for(m=0;m<j;m++)print
    c[m],a[c[m]]
  6. }’
  7.  

复制代码

6.  多个文本编辑:这里主要指的是待处理的文本之间的格式上有区别,如分隔符不同,;或是待处理文本需提取的信息的位置不同,如不同的列或行。
<例1>:

  1.  
  2. cat file1
  3. g1.1 2
  4. g2.2 4
  5. g2.1 5
  6. g4.1 3
  7. cat file2
  8. g1.1 2
  9. g1.2 3
  10. g4.1 4
  11. cat file3
  12. g1.2 3
  13. g5.1 3
  14.  

复制代码

要求输出:

  1.  
  2. g1.1 2 2 –
  3. g1.2 – 3 3
  4. g2.2 4 – –
  5. g2.1 5 – –
  6. g4.1 3 4 –
  7. g5.1 – – 3
  8.  

复制代码

实现代码如下:

  1.  
  2. awk ‘{a[ARGIND”
    “$1]=$2 #
    ARGIND是当前命令行文件的位置(从0开始),将它和第一列的value作为下标,建立数组a。
  3.        b[$1] 
     #将第一列的value作为下标,建立数组b,目的是在读完所有文件之后,能得到第一列value的uniqe-list。
  4.         }
  5. END{ 
  6.         for(i in b)
  7.                
    printf i” ” 
  8.                
    for(j=1;j<=ARGIND;j++) printf “%s “, a[j” “i]?a[j” “i]:”-”
    #此时的ARGIND值为3.
  9. print “” 
  10.                
    }
  11.         }’ file1
    file2 file3
  12.  

复制代码

网站地图xml地图