012011
 

第二部分 文本过滤

七、Unix下的正则表达式

Unix下的正则表达式居然并不统一,这让我感到很困惑,似乎不同的命令中正则表达式的格式还不相同,或许是我接触的还是太少吧,这个问题以后再考略一下。这里先简单写写。

^               只匹配开头
$               只匹配结尾,特殊的:^$匹配空行
*               该字符前的模式重复0到多次
+               该字符前的模式重复1到多次
?               该字符前的模式重复0或1次
[]              表范围,如[a-zA-Z]或[1-5]等
[^pattern]      表不匹配该模式,如[^a-zA-Z]匹配非字母型字符
\               转义字符
.               表单个任意字符
pattern\{n\}    该模式重复恰好n次,加反斜线是为了{}的正常使用
pattern\{n,\}   该模式重复至少n次
pattern\{n,m\}  该模式重复n到m次

八、grep的使用

grep允许对文本进行模式查找,如果找到模式匹配,则打印匹配模式的所有行。grep是功能和操作都比较简单的文本查找命令。

grep "pattern" filename    返回filename文件中所有匹配pattern的行
grep -c "pattern" filename   返回匹配的行数
grep -n "pattern" filename   在返回的行前加上它在filename中的行号
grep -v "pattern" filename   返回不匹配pattern的行
grep -i "pattern" filename   忽略pattern的大小写
pattern后跟随 \> 可以实现精确匹配

grep -E 可使用扩展模式匹配,即可以使用“与”“或”操作
    如 grep -E "216|219" data.f

有一些国际标准类可以代替正则表达式,下面列举出的是其中部分:
    [[:upper:]] 等价于 [A-Z]
    [[:lower:]] 等价于 [a-z]
    [[:digit:]] 等价于 [0-9]
    [[:alnum:]] 等价于 [A-Za-z0-9]
    [[:space:]] 等价于 空格或TAB
    [[:alpha:]] 等价于 [a-zA-Z]

grep可以用于普通文件,也可接受管道传来的值,还可以接受字符串,如
    $ STR = "mary pauline simon"
    $ echo $STR | grep "mary"
    返回 mary pauline simon

egrep -f pattern_file data_file 可以从一个文件接收pattern

 

九、awk命令的使用

awk可以用于从文本文件从抽取域,也就是按列抽取,能够进行比较复杂的动作,扩展性比grep要好很多,也复杂许多,这里只写一些简单的应用方式。

命令行调用awk:
    awk [-F域分隔符] '命令' 要操作的文件
awk文件方式:
    1,首行指明 #! /usr/bin/awk -f
    2,命令行awk -f 脚本awk …

awk脚本分为两大部分。一是模式:用来匹配,以触发动作;二是动作:用来执行匹配后的行为,这也是awk的强大之处。
域,即一列,用$1 $2 … $n来表示。其中$0表示所有域。
BEGIN{…} 执行初始化的动作,比如打印报头或者初始化几个变量。
END{…} 执行结尾动作,比如打印报尾,或者计算平均值等。

在awk中,模式要用斜线括起来, /pattern/
~ 匹配模式(非精确匹配); !~ 不匹配模式; 还可以使用比较运算符。

如果没有指明动作,则默认打印匹配的行。
一个较通用的例子
   $ awk '{if ($1 == "Yellow" && $4 ~ /Good/) print $1,"\t",$4}' data.file

内置变量
    ARGC      命令行参数个数
    ARGS      命令行参数排列。这两个用于使用传入awk脚本的参数。
    ENVIRON   支持队列中系统环境变量的使用,ENVIRON["EDITOR"] = "Vi"
    FILENAME  awk正在处理的文本文件名
    FNR       目前操作的记录数
    NR        记录数目
    NF        域的数目
    FS        设置输入域分隔符,等价于命令行-F选项,默认为空格
    RS        控制记录分隔符,默认为"\n"
    OFS       输出域分隔符,print用,默认为空格。
    ORS       输出记录分隔符,print用,默认为"\n"

如果一行之内有数个语句,要用分号分隔,if后的语句块用{}括起来。大部分操作和运算都和C语言一致。

 

内置函数    
    gsub(r,s) 在整个$0中用s替代r
    gsub(r,s,t) 在整个t中用s替代r
    index(s,t) 返回s中字符串t的第一位置
    length(s) 返回s长度
    match(s,r) 测试s是否包含匹配r的字符串
    split(s,a,fs) 使用域分隔符fs,将串s分解成数组a
    sub(r,s) 发现并替换模式r第一次出现位置,替换为s
    substr(s,p) 返回字符串s中从p开始的后缀部分
    substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分

awk脚本中如果定义了变量,并需要输入的,可以在'command’后,input_file前,输入。
    如 awk '{if($3<AGE) print $0}' AGE=10 data.txt

数组的使用<尚未验证>
    awk中的数组,比如通过split函数得来的,可以通过下标,或者迭代使用。
    下标起始值为1,这点很独特。
    还可以使用 for (i in array) {print array[i]}

 Leave a Reply

(必须填写)

(必须填写,邮件地址不会被泄露)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>