shell习题

1、数据文件格式如下:

 1 0        1        2        3        4        5        6        ch1
2 0 1 4 3 4 5 6 ch3
3 0 1 2 3 4 5 6 ch2
4 0 1 3 3 4 5 6 ch1
5 0 1 6 3 4 5 6 ch1
6 0 1 1 3 4 5 6 ch1
7 0 1 2 3 4 5 6 ch2
8 0 1 2 3 4 5 6 ch2
9 0 1 2 3 4 5 6 ch4
10 0 1 2 3 4 5 6 ch3
11 0 1 2 3 4 5 6 ch1
12 0 1 2 3 4 5 6 ch1

要按照第8列,分类,把文件拆分,分别写入不同的文件里。文件名为:ch1.txt、ch2.txt、ch3.txt。

$ awk 'print >>$NF".txt"' test 

注意:NF记录域的个数。

2、合并将只有一个域的行合并到有多个域的行中.

1 9360338 Q  A
2 9360312 Q B
3 1
4 2
5 93603we Q C
6 9312338 Q D
7 1
8 2
9 93sddd3 Q E

答案:

 awk '/^\w/{if(NR!=1)print a;a=$0;next}{a=a FS $1}ENE{print a}' tmp

解释如下:

\w :匹配包括下划线的任何单词字符,等价于 [A-Z a-z 0-9_]
\W :匹配任何非单词字符,等价于 [^A-Z a-z 0-9_]
NR:记录数量。
FS:分隔符
next关键字:强制AWK停止正在处理的记录,也就是说next后面的action都不会对当前的record执行。
总是处理当前记录,打印之前的记录,所以最后加上END,处理最后一行。

3、将两个文件连接,文件内容如下:

 1 $ cat file1 
2 23 中西
3 98
4 34 西瓜
5 53 巴巴
6
7 $ cat file2
8 巴巴 c
9 红 b
10 西瓜 d
11 中西 f

答案:

awk 'NR==FNR{a[$2]=$1}NR!=FNR{print $1, a[$1]}' file1 file2

awk的数据输入有两个来源,标准输入和文件,后一种方式支持多个文件,如
1、shell的Pathname Expansion方式:awk '{...}'  *.txt      #  *.txt先被shell解释,替换成当前目录下的所有*.txt,如当前目录有1.txt和2.txt,则命令最终为awk '{...}' 1.txt 2.txt
2、直接指定多个文件: awk '{...}' a.txt b.txt c.txt ...
awk对多文件的处理流程是,依次读取各个文件内容,如上例,先读a.txt,再读b.txt....
那么,在多文件处理的时候,如何判断awk目前读的是哪个文件,而依次做对应的操作呢?
1、当awk读取的文件只有两个的时候,比较常用的有两种方法
一种是awk 'NR==FNR{...}NR>FNR{...}'  file1 file2   或awk 'NR==FNR{...}NR!=FNR{...}' file1 file2
另一种是 awk 'NR==FNR{...;next}{...}' file1 file2
了解了FNR和NR这两个awk内置变量的意义就很容易知道这两种方法是如何运作的

FNR         The input record number in the current input file.       #已读入当前文件的记录数
NR          The total number of input records seen so far.            #已读入的总记录数
next        Stop processing the current input record.  The next input record  is
                             read  and  processing  starts over with the first pattern in the AWK
                             program.  If the end of the input data is reached, the END block(s),
                             if any, are executed.

对于awk 'NR==FNR{...}NR>FNR{...}'  file1 file2
读入file1的时候,已读入file1的记录数FNR一定等于awk已读入的总记录数NR,因为file1是awk读入的首个文件,故读入file1时执行前一个命令块{...}
读入file2的时候,已读入的总记录数NR一定>读入file2的记录数FNR,故读入file2时执行后一个命令块{...}

对于awk 'NR==FNR{...;next}{...}' file1 file2
读入file1时,满足NR==FNR,先执行前一个命令块,但因为其中有next命令,故后一个命令块{...}是不会执行的
读入file2时,不满足NR==FNR,前一个命令块{..}不会执行,只执行后一个命令块{...}

2、当awk处理的文件超过两个时,显然上面那种方法就不适用了。因为读第3个文件或以上时,也满足NR>FNR (NR!=FNR),显然无法区分开来。
所以就要用到更通用的方法了:
a、ARGIND 当前被处理参数标志: awk 'ARGIND==1{...}ARGIND==2{...}ARGIND==3{...}... ' file1 file2 file3 ...
b、ARGV 命令行参数数组:   awk 'FILENAME==ARGV[1]{...}FILENAME==ARGV[2]{...}FILENAME==ARGV[3]{...}...' file1 file2 file3 ...    
c、把文件名直接加入判断: awk 'FILENAME=="file1"{...}FILENAME=="file2"{...}FILENAME=="file3"{...}...' file1 file2 file3 ...           #没有前两种通用

 

4、将某个文件的两个合并。

1 $ cat tmp 
2 101,102
3 201,202
4 301,302
5 401,402
6 501,502

答案:

$ sed '{N;s/\n/,/}' tmp


解释:

`N'
     Add a newline to the pattern space, then append the next line of
     input to the pattern space.  If there is no more input then `sed'
     exits without processing any more commands.

把输入的下一行添加到模式空间里,然后替换换行为逗号。

posted @ 2012-03-02 15:50  leealways87  阅读(276)  评论(0编辑  收藏  举报