awk 正则表达式
前言:使用awk作为文本处理工具,正则表达式是少不了的。 要掌握这个工具的正则表达式使用。其实,我们不必单独去学习它的正则表达式。正则表达式就像一门程序语言,有自己语法规则已经表示意思。 对于不同工具,其实大部分表示意思相同的。在linux众多文本处理工具(awk,sed,grep,perl)里面用到正则表达式。其实就只有3种类 型。详细可以参考:linux shell 正则表达式(BREs,EREs,PREs)差异比较 。只要是某些工具是属于某种类型的正则表达式。那么它的语法规则基本一样。 通过那篇文章,我们知道awk的正则表达式,是属于:扩展的正则表达式(Extended Regular Expression 又叫 Extended RegEx 简称 EREs)。
一、awk Extended Regular Expression (ERES)基础表达式符号介绍
字符 | 功能 |
---|---|
+ | 指定如果一个或多个字符或扩展正则表达式的具体值(在 +(加号)前)在这个字符串中,则字符串匹配。命令行:
awk '/smith+ern/' testfile 将包含字符 smit,后跟一个或多个 h 字符,并以字符 ern 结束的字符串的任何记录打印至标准输出。此示例中的输出是: smithern, harry smithhern, anne |
? | 指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:
awk '/smith?/' testfile 将包含字符 smit,后跟零个或一个 h 字符的实例的所有记录打印至标准输出。此示例中的输出是: smith, alan smithern, harry smithhern, anne smitters, alexis |
| | 指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:
awk '/allen | alan /' testfile 将包含字符串 allen 或 alan 的所有记录打印至标准输出。此示例中的输出是: smiley, allen smith, alan |
( ) | 在正则表达式中将字符串组合在一起。命令行:
awk '/a(ll)?(nn)?e/' testfile 将具有字符串 ae 或 alle 或 anne 或 allnne 的所有记录打印至标准输出。此示例中的输出是: smiley, allen smithhern, anne |
{m} | 指定如果正好有 m 个模式的具体值位于字符串中,则字符串匹配。命令行:
awk '/l{2}/' testfile 打印至标准输出 smiley, allen |
{m,} | 指定如果至少 m 个模式的具体值在字符串中,则字符串匹配。命令行:
awk '/t{2,}/' testfile 打印至标准输出: smitters, alexis |
{m, n} | 指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m <= n),则字符串匹配。命令行:
awk '/er{1, 2}/' testfile 打印至标准输出: smithern, harry smithern, anne smitters, alexis |
[String] | 指定正则表达式与方括号内 String 变量指定的任何字符匹配。命令行:
awk '/sm[a-h]/' testfile 将具有 sm 后跟以字母顺序从 a 到 h 排列的任何字符的所有记录打印至标准输出。此示例的输出是: smawley, andy |
[^ String] | 在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:
awk '/sm[^a-h]/' testfile 打印至标准输出: smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis |
~,!~ | 表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:
awk '$1 ~ /n/' testfile 将第一个字段包含字符 n 的所有记录打印至标准输出。此示例中的输出是: smithern, harry smithhern, anne |
^ | 指定字段或记录的开头。命令行:
awk '$2 ~ /^h/' testfile 将把字符 h 作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是: smithern, harry |
$ | 指定字段或记录的末尾。命令行:
awk '$2 ~ /y$/' testfile 将把字符 y 作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是: smawley, andy smithern, harry |
. (句号) | 表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:
awk '/a..e/' testfile 将具有以两个字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是: smawley, andy smiley, allen smithhern, anne |
*(星号) | 表示零个或更多的任意字符。命令行:
awk '/a.*e/' testfile 将具有以零个或更多字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是: smawley, andy smiley, allen smithhern, anne smitters, alexis |
\ (反斜杠) | 转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:
/a\/\// 将与模式 a // 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。 |
与PERs相比,主要是一些结合类型表示符没有了:包括:”\d,\D,\s,\S,\t,\v,\n,\f,\r”其它功能基本一样的。 我们常见的软件:javascript,.net,java支持的正则表达式,基本上是:EPRs类型。
二、awk 常见调用正则表达式方法
- awk语句中:
awk ‘/REG/{action}’
/REG/为正则表达式,可以将$0中,满足条件记录 送入到:action进行处理.
- awk正则运算语句(~,~!等同!~)
[chengmo@centos5 ~]$ awk 'BEGIN{info="this is a test";if( info ~ /test/){print "ok"}}'
ok
- awk内置使用正则表达式函数
gsub( Ere, Repl, [ In ] )
sub( Ere, Repl, [ In ] )
match( String, Ere )
split( String, A, [Ere] )
详细函数使用,可以参照:linux awk 内置函数详细介绍(实例)
通过上面细述,不知道大家有没有对awk正则表达式有一个更加清楚的认识。 有什么问题可以与我交流!
awk用-F指定多分隔符及正则表达式
命令行选项 -F"[@ /t]" 告诉awk @, 空格和Tab都是字段分隔符,例如:
awk -F"[@ /t]" '{print $2,$3}' test
以@,空格,Tab键分割test文件的每一行,并输出第二、第三列。
awk '$2~/^(126|yahoo)/{print $2, $3}' test
如果改行的第二个字段以"123"或"yahoo"开始,则输出改行的第二、第三列。
awk '$1~/[0-9][0-9]$/{print $1, $3}' test
如果改行的最后两个字段以数字结束,则输出改行的第一、第三列。
awk '/mail/{print $0}' test
输出test文件中含有"mail"字符串的行
$awk '$2~/mail/{print $0}' test
输出test文件中第二个字段含有"mail"字符串的行
$awk '$2 == "gmail.com"{$1 = "ggg";print}' test
输出test文件中第二个字段是"gmail.com"的行,并把改行第一列改为"ggg"
awk '$2 == "gmail.com"{$1 = "ggg"}{print}' test
输出test文件中所有行,并且如果第二个字段是"gmail.com",把改行第一列改为"ggg"
awk '{IGNORECASE=1;if($2 ~/^[a-z]/&& $2~/net$/){print $0}}' test
打开test文件,忽略字母大小写,如果第二字段以[a-z]开头,并以"net"结尾,则输出该行。
AWK记录、字段、模式、跨平台移植及正则表达式 2014-06-02 20:39:20
分类: Linux
1,
记录分隔符:默认行输入和输出的分隔符都是回车,保存在RS和ORS内部变量中。变量$0:awk每次一行取得整条记录,$0随之改变,同时内部变量NF(字段的总数)也随之变化。变量NR:每条记录的行号,处理完一行将会加1,所以全部处理完后可以理解成行数的总数。
2,
FS: Field Separator
OFS: Output Field Separator
RS: Row Separator (行分隔符)
ORS: Output Row Separator
NF: Number of Fields
NR: Number of Rows
正在处理的哪一行就变成了$0
3,
[root@rhel helinbash]# gawk '{print NR,"--> ",$0}' /etc/passwd
1 --> root:x:0:0:root:/root:/bin/bash
2 --> bin:x:1:1:bin:/bin:/sbin/nologin
3 --> daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 --> adm:x:3:4:adm:/var/adm:/sbin/nologin
5 --> lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 --> sync:x:5:0:sync:/sbin:/bin/sync
7 --> shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 --> halt:x:7:0:halt:/sbin:/sbin/halt
9 --> mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 --> news:x:9:13:news:/etc/news:
11 --> uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
12 --> operator:x:11:0:operator:/root:/sbin/nologin
13 --> games:x:12:100:games:/usr/games:/sbin/nologin
14 --> gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
15 --> ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
16 --> nobody:x:99:99:Nobody:/:/sbin/nologin
17 --> nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
18 --> vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
19 --> rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin
20 --> mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
21 --> smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
22 --> pcap:x:77:77::/var/arpwatch:/sbin/nologin
23 --> ntp:x:38:38::/etc/ntp:/sbin/nologin
24 --> dbus:x:81:81:System message bus:/:/sbin/nologin
25 --> avahi:x:70:70:Avahi daemon:/:/sbin/nologin
26 --> sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
27 --> rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
28 --> nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
29 --> haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
30 --> avahi-autoipd:x:100:101:avahi-autoipd:/var/lib/avahi-autoipd:/sbin/nologin
31 --> xfs:x:43:43:X Font Server:/etc/X11/fs:/sbin/nologin
32 --> gdm:x:42:42::/var/gdm:/sbin/nologin
33 --> sabayon:x:86:86:Sabayon user:/home/sabayon:/sbin/nologin
34 --> oracle:x:500:500::/home/oracle:/bin/bash
35 --> named:x:25:25:Named:/var/named:/sbin/nologin
[root@rhel helinbash]#
4,
[root@rhel helinbash]# gawk '{print NR,"--> ",$1}' names.txt
1 --> Tom
2 --> Molly
3 --> John
4 --> yang
[root@rhel helinbash]# gawk '{print NR,":",NF,"--> ",$1}' names.txt
1 : 3 --> Tom
2 : 3 --> Molly
3 : 3 --> John
4 : 3 --> yang
[root@rhel helinbash]#
5,
[root@rhel helinbash]# vim names.txt
[root@rhel helinbash]# gawk '{print NR,":",NF,"--> ",$1}' names.txt
1 : 3 --> Tom
2 : 3 --> Molly
3 : 3 --> John
4 : 4 --> yang
[root@rhel helinbash]# cat names.txt
Tom Savage 100
Molly Lee 200
John Doe 300
yang wawa asdfas -121212
[root@rhel helinbash]#
[root@rhel helinbash]# cat names.txt
Tom Savage 100
Molly Lee 200
John Doe 300
yang wawa asdfas -121212
[root@rhel helinbash]#
6,
[root@rhel helinbash]# gawk '{print $1,$NF}' names.txt
Tom 100
Molly 200
John 300
yang -121212
[root@rhel helinbash]#
二,跨平台数据移植格式转换
1,
把linux文本转化为window文本
[root@rhel helinbash]# gawk '{ORS="\r\n";RS="\n";print $0}' names.txt > names.win
[root@rhel helinbash]# cat names.win
Tom Savage 100
Molly Lee 200
John Doe 300
yang wawa asdfas -121212
2,
把window文本转化为linux版本
[root@rhel helinbash]# gawk '{ORS="\n";RS="\r\n";print $0}' names.win > names.linux
[root@rhel helinbash]# cat names.linux
Tom Savage 100
Molly Lee 200
John Doe 300
yang wawa asdfas -121212
[root@rhel helinbash]#
三,模式
1,
awk模式用来控制输入的文本行执行什么样的操作
模式为正则表达式
模式具有着隐式if语句
模式写在模式操作符两个“//”中
2,
[root@rhel helinbash]# gawk '/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@rhel helinbash]#
3,
操作
格式
模式{操作语句1;操作语句2;....;}
或者
模式
{
操作语句1
操作语句2
........
}
4,
模式对单列处理
[root@rhel helinbash]# gawk -F: '/bash$/{ print $1}' /etc/passwd
root
oracle
[root@rhel helinbash]# gawk -F: '$7 ~ /bash$/{ print $1}' /etc/passwd
root
oracle
[root@rhel helinbash]#
[root@rhel helinbash]# gawk -F: '$7 !~ /bash$/{ print $1}' /etc/passwd
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
uucp
operator
games
gopher
ftp
nobody
nscd
vcsa
rpc
mailnull
smmsp
pcap
ntp
dbus
avahi
sshd
rpcuser
nfsnobody
haldaemon
avahi-autoipd
xfs
gdm
sabayon
named
[root@rhel helinbash]#
四,正则表达式
1,
很多地方都是用到正则表达式来匹配特定的信息
^ 串首
$ 串尾
. 匹配单个任意字符
* 匹配零个或多个前面的字符
+ 匹配一个或多个前面的字符
? 匹配零个或一个前面的字符
[ABC] 匹配括号中给出的任一个字符
[A-Z] 匹配A到Z之间的任一个字符
A|B 匹配二选一,或者的意思,等同于[AB]
(AB)+ 匹配一个或多个括号中的组合
\* 星号本身,转义星号本身
2,
[root@rhel helinbash]# gawk '/^a/' test.txt
a
ab
abab
abbb
ababab
aaab
[root@rhel helinbash]# gawk '/^a$/' test.txt
a
[root@rhel helinbash]# gawk '/a$/' test.txt
a
baaa
[root@rhel helinbash]# gawk '/..../' test.txt
abab
abbb
ababab
aaab
baaa
[root@rhel helinbash]# gawk '/^....&/' test.txt
[root@rhel helinbash]# gawk '/^....$/' test.txt
abab
abbb
aaab
baaa
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
[root@rhel helinbash]#
3,
[root@rhel helinbash]# vim test.txt
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
[root@rhel helinbash]# gawk '/^....$/' test.txt
abab
abbb
aaab
baaa
c.tx
[root@rhel helinbash]# gawk '/^.\...$/' test.txt
c.tx
[root@rhel helinbash]#
4,
[root@rhel helinbash]# gawk '/^a*$/' test.txt
a
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
5,
[root@rhel helinbash]# vim test.txt
[root@rhel helinbash]# gawk '/^a*$/' test.txt
a
aaaaa
aaaa
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
aaaaa
aaaa
[root@rhel helinbash]#
6,
[root@rhel helinbash]# gawk '/^a*$/' test.txt
a
aaaaa
aaaa
[root@rhel helinbash]# vim test.txt
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
aaaaa
aaaa
[root@rhel helinbash]# gawk '/^a*$/' test.txt # 注: * 可以匹配空行就是出现了0次
a
aaaaa
aaaa
[root@rhel helinbash]# gawk '/^a+$/' test.txt # 注: 这个不可以匹配空行至少出现1次
a
aaaaa
aaaa
[root@rhel helinbash]#
[root@rhel helinbash]# gawk '/^a?$/' test.txt
a
[root@rhel helinbash]#
[root@rhel helinbash]# gawk '/^[ab]*/' ./test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx #为什么会出现,因为ab出现了0次,也就是*的含义
aaaaa
aaaa
[root@rhel helinbash]# gawk '/^[ab]*$/' ./test.txt
a
ab
abab
abbb
ababab
aaab
baaa
aaaaa
aaaa
[root@rhel helinbash]#
[root@rhel helinbash]# gawk '/^[^ab]*$/' ./test.txt
c.tx
[root@rhel helinbash]#
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
aaaaa
aaaa
[root@rhel helinbash]#
7,
[root@rhel helinbash]# cat test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
aaaaa
aaaa
dddddddddddddd
ffffffffff
faaaaaaaaaa
kjjjjjjj
[root@rhel helinbash]# gawk '/^[^ab]*$/' ./test.txt
c.tx
dddddddddddddd
ffffffffff
kjjjjjjj
[root@rhel helinbash]#
8,
[root@rhel helinbash]# gawk '/(ab)*/' test.txt
a
ab
abab
abbb
ababab
aaab
baaa
c.tx
aaaaa
aaaa
dddddddddddddd
ffffffffff
faaaaaaaaaa
kjjjjjjj
[root@rhel helinbash]#
[root@rhel helinbash]# gawk '/^(ab)*$/' test.txt
ab
abab
ababab
[root@rhel helinbash]#
9,
[root@rhel helinbash]# gawk '/^(ab)\{3\}*$/' test.txt #{3}这种不支持
[root@rhel helinbash]#
linux awk 正则表达式、正则运算符详细介绍
一、awk Extended Regular Expression (ERES)基础表达式符号介绍
字符 | 功能 |
---|---|
+ | 指定如果一个或多个字符或扩展正则表达式的具体值(在 +(加号)前)在这个字符串中,则字符串匹配。命令行:
awk '/smith+ern/' testfile 将包含字符 smit,后跟一个或多个 h 字符,并以字符 ern 结束的字符串的任何记录打印至标准输出。此示例中的输出是: smithern, harry smithhern, anne |
? | 指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:
awk '/smith?/' testfile 将包含字符 smit,后跟零个或一个 h 字符的实例的所有记录打印至标准输出。此示例中的输出是: smith, alan smithern, harry smithhern, anne smitters, alexis |
| | 指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:
awk '/allen | alan /' testfile 将包含字符串 allen 或 alan 的所有记录打印至标准输出。此示例中的输出是: smiley, allen smith, alan |
( ) | 在正则表达式中将字符串组合在一起。命令行:
awk '/a(ll)?(nn)?e/' testfile 将具有字符串 ae 或 alle 或 anne 或 allnne 的所有记录打印至标准输出。此示例中的输出是: smiley, allen smithhern, anne |
{m} | 指定如果正好有 m 个模式的具体值位于字符串中,则字符串匹配。命令行:
awk '/l{2}/' testfile 打印至标准输出 smiley, allen |
{m,} | 指定如果至少 m 个模式的具体值在字符串中,则字符串匹配。命令行:
awk '/t{2,}/' testfile 打印至标准输出: smitters, alexis |
{m, n} | 指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m <= n),则字符串匹配。命令行:
awk '/er{1, 2}/' testfile 打印至标准输出: smithern, harry smithern, anne smitters, alexis |
[String] | 指定正则表达式与方括号内 String 变量指定的任何字符匹配。命令行:
awk '/sm[a-h]/' testfile 将具有 sm 后跟以字母顺序从 a 到 h 排列的任何字符的所有记录打印至标准输出。此示例的输出是: smawley, andy |
[^ String] | 在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:
awk '/sm[^a-h]/' testfile 打印至标准输出: smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis |
~,!~ | 表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:
awk '$1 ~ /n/' testfile 将第一个字段包含字符 n 的所有记录打印至标准输出。此示例中的输出是: smithern, harry smithhern, anne |
^ | 指定字段或记录的开头。命令行:
awk '$2 ~ /^h/' testfile 将把字符 h 作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是: smithern, harry |
$ | 指定字段或记录的末尾。命令行:
awk '$2 ~ /y$/' testfile 将把字符 y 作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是: smawley, andy smithern, harry |
. (句号) | 表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:
awk '/a..e/' testfile 将具有以两个字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是: smawley, andy smiley, allen smithhern, anne |
*(星号) | 表示零个或更多的任意字符。命令行:
awk '/a.*e/' testfile 将具有以零个或更多字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是: smawley, andy smiley, allen smithhern, anne smitters, alexis |
\ (反斜杠) | 转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:
/a\/\// 将与模式 a // 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。 |
与PERs相比,主要是一些结合类型表示符没有了:包括:”\d,\D,\s,\S,\t,\v,\n,\f,\r”其它功能基本一样的。 我们常见的软件:javascript,.net,java支持的正则表达式,基本上是:EPRs类型。
二、awk 常见调用正则表达式方法
awk语句中:
代码如下:
/REG/为正则表达式,可以将$0中,满足条件记录 送入到:action进行处理.
awk正则运算语句(~,~!等同!~)
代码如下:
ok
awk内置使用正则表达式函数
代码如下:
sub( Ere, Repl, [ In ] )
match( String, Ere )
split( String, A, [Ere] )
详细函数使用,可以参照:linux awk 内置函数详细介绍(实例)
通过上面细述,不知道大家有没有对awk正则表达式有一个更加清楚的认识。 有什么问题可以与我交流!
对于awk而言,正则表达式是置于两个正斜杠之间(‘’)、由字符组成的模式。Awk支持 使用正则表达式元字符对正则表达式进行某种方式修改。如果输入行中的某个字符串与正则表达式相匹配,则最终条件为真,于是执行与该表达式关联的所有操作。 如果没有指定操作,则打印与正则表达式匹配的记录
元字符 | 说明 |
^ | 在串首匹配 |
$ | 在串尾匹配 |
. | 匹配单个任意字符 |
* | 匹配零个或多个前导字符 |
+ | 匹配一个或多个前导字符 |
? | 匹配零个或一个前导字符 |
|(A|B) | 指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配,匹配A或B |
[ABC] | 匹配指定字符组(即A、B和C)中任一字符 |
[^ABC] | 匹配任何一个不在指定字符组(即A、B和C)中的字符 |
[A-Z] | 匹配A至Z之间的任一字符 |
(AB)+ | 将字符串组合在一起,匹配一个或多个AB的组合,例如:AB、ABAB |
~,!~ | 表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句 |
{m, n} | 指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m<= n),则字符串匹配 |
\ | 转义字符。位于正则表达式中具有特殊含义的任何字符之前时,转义字符除去其任何特殊含义 |
& | 用于替代串中,代表查找串中匹配到的内容 |
表-Awk的正则表达式元字符
元字符 | 说明 |
\<>/ | 单词定位 |
\(\) | 向前引用 |
\{\} |
重复 |
本教程首先对正则表达式进行了基本的解释,然后介绍了 grep
和 sed
。grep
是一个强大的搜索实用程序,而 sed
则是一个更加强大的搜索和替换实用程序。awk
则更进一步,它在全功能的命令行编程语言中使用正则表达式。正如 sed
一样,当在命令行上使用 awk
时,它接受基于行的输入。awk
一次解释一行输入,但是与 sed
不同,它将该行上的每个部分作为变量来处理,这些变量可用作内联代码的输入和输出。
应该指出的是,AWK(大写)是一个可用于编写脚本(而不只是在命令行上使用)的全功能编程语言,但本教程集中于 awk
,后者是动态解释 AWK 命令的命令行实用程序。
顺便提一下,任何人阅读到这里都会考虑如何实际运用所学到的知识,我刚才就使用 grep
在某些旧代码中搜索理想的 awk
示例:
grep awk */*.pl |
大多数系统管理员或程序员每天都会看到这些工具的应用。下面是我的输出中的一些行:
Edaemon/m_checkcurrentdisk.pl:$freespace = `awk '(NR==1) {print \$4 / 1024 / 1024}' grep.tmp`; Edaemon/m_getdatetime.pl:$month = `awk '(NR==1) {print \$2}' datetime.txt`; Odaemon/odaemon.beowulf.dvd.pl:$filesize = `awk '(NR==1) {print \$1}' temp.txt`; |
这些是非常好的示例,因为它们说明了非常基础的 awk
应用。对于您的第一次尝试,甚至可以使它更简单。对于您的 awk
测试,请在一个空目录中创建以下文件(每个文件的内容无关紧要,并且它们可以是空的)。
Screenshot_1.jpg Screenshot_2.jpg Screenshot_3.jpg awk.txt regular.txt sed.txt |
使用 ls 的输出作为 awk 的输入
缺省情况下,awk
读取输入文件中的每一行,并将内容分离为由空格确定的变量。在非常简单的示例中,您可以使用 ls
的输出作为 awk
的输入并打印结果。此示例结合使用管道字符 (|) 和 ls
来将输出发送到 awk
:
ls | awk ' { print $1 } ' |
awk
随后打印每行上的第一项,在此例中为每行上的唯一项:
Screenshot_1.jpg Screenshot_2.jpg Screenshot_3.jpg awk.txt regular.txt sed.txt |
使用 ls -l 来为 awk 生成多列输入
这确实是非常基本的功能。对于下一个示例,请使用 ls -l
来为 awk
生成多列输入:
ls -l |
不同系统的 ls
实现稍有差别,下面是一些示例输出:
total 432 -rw-rw-rw- 1 guest guest 169074 Oct 15 14:51 Screenshot_1.jpg -rw-rw-rw- 1 guest guest 23956 Oct 15 20:56 Screenshot_2.jpg -rw-rw-rw- 1 guest guest 12066 Oct 15 20:57 Screenshot_3.jpg -rw-r--r-- 1 tuser tuser 227 Oct 15 20:16 awk.txt -rw-r--r-- 1 tuser tuser 233 Oct 15 19:35 regular.txt -rw-r--r-- 1 tuser tuser 227 Oct 15 23:16 sed.txt |
请注意,文件所有者是每行上的第三个项,文件名是每行上的第九个项(缺省情况下,awk
中的项之间用空格分隔)。通过打印每行上的第三和第九个变量,您可以使用 awk
来从该列表提取文件所有者和文件名。下面是完成这项工作的命令:
ls -l | awk ' { print $3 " " $9 } ' |
您将注意到,awk
中的 print
命令有两个引号,而且引号中有一个空格。这只是为了在输出的文件所有者和文件名之间打印一个空格:
guest Screenshot_1.jpg guest Screenshot_2.jpg guest Screenshot_3.jpg tuser awk.txt tuser regular.txt tuser sed.txt |
您可以在 awk
打印语句中的变量之间的引号中放置任何文本。
使用正则表达式来指定行
现在您已经学习了如何使用 awk
的基础知识,但本教程不是关于正则表达式的吗?awk
中大量使用了正则表达式。最常见的示例是在 awk
命令前附加一个正则表达式,用于指定您想要操作的行。与 sed
一样,awk
中的正则表达式位于两个正斜杠之间。例如,如果您只希望操作 tuser
所拥有的文件,则可以使用以下命令:
ls -l | awk ' /tuser/ { print $3 " " $9 } ' |
该命令产生以下输出:
tuser awk.txt tuser regular.txt tuser sed.txt |
更改文件扩展名
在另一个示例中,您可能希望更改每个文本文件的文件扩展名而不更改图像文件。为此,您将需要使用句点而不是空格来分隔输入变量,然后使用正则表达式来指示您仅希望搜索文本文件。若要基于句点来分隔变量,可以使用 -F
标志,后跟后跟您希望使用的字符(用引号引起来)。尝试此示例,通过管道将 awk
输出发送到某个 Shell(此 Shell 将执行 awk
生成的命令):
s | awk -F"." ' /txt/ { print "mv " $1 "." $2 " " $1 ".doc" } ' | bash |
后续的 ls -l
将显示新的文件名:
-rw-rw-rw- 1 guest guest 169074 Oct 15 14:51 Screenshot_1.jpg -rw-rw-rw- 1 guest guest 23956 Oct 15 20:56 Screenshot_2.jpg -rw-rw-rw- 1 guest guest 12066 Oct 15 20:57 Screenshot_3.jpg -rw-r--r-- 1 tuser tuser 227 Oct 15 20:16 awk.doc -rw-r--r-- 1 tuser tuser 233 Oct 15 19:35 regular.doc -rw-r--r-- 1 tuser tuser 227 Oct 15 23:16 sed.doc |
记住,这些只是 awk
的入门基础知识,但是 AWK 是一种全功能的编程语言,所具有的功能远远超出了本教程所介绍的内容。请查看一下 awk man
页。如果您希望学习更多的知识,花钱买一本优秀的图书是明智的。
AWK是一种优良的文本处理工具。它不仅是linux中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据库访问语言(其名称得自 于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识
一、AWK的用法:
1、在命令行模式的直接使用。 格式为: awk ‘pattern {action}’
2、将awk命令写入脚本,并以#!/bin/awk -f命令解释器作为脚本的首行,设置脚本的可执行权限,通过键入脚本名称来调用它。格式为./testscript.awk filename。等同于shell脚本的方法。
3、将awk命令插入一个单独文件然后执行。格式为 awk -f awkscript filename
第
一种格式常见的是awk 'BEGIN {print "this is the start"}{print $1,$2,$3}END{print
"this is the end"}'
filename。其中BEGIN和END中间是模式,END后是动作。BEGIN和END可以省去,模式一般是匹配搜索使用
二、AWK排查错误常见的问题
1、确保整个AWK用单引号括起来;2、确保单引号内所有的括号或引号成对出现;3、确保用大括号括起动作语句,用小括号括起条件语句;4有时候要检查是否有文件名或者BEGIN等
三、AWK内置字符串变量函数
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,放在数组a里。返回段数的数值,
|
sprint(fmt,exp)
|
返回经fmt格式化后的exp
|
sub(r,s)
|
用$0中最左边最长的子串代替s
|
substr(s,p)
|
返回字符串s中从p开始的后缀部分
|
substr(s,p,n)
|
返回字符串s中从p开始长度为n的后缀部分
|
四、AWK的内置环境变量
$n | 当前记录的第n个字段,字段间由FS分隔。 |
$0 | 完整的输入记录。在文本中一般指行信息内容 |
ARGC | 命令行参数的数目。 |
ARGIND | 命令行中当前文件的位置(从0开始算)。 |
ARGV | 包含命令行参数的数组。 |
CONVFMT | 数字转换格式(默认值为%.6g) |
ENVIRON | 环境变量关联数组。 |
ERRNO | 最后一个系统错误的描述。 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔)。 |
FILENAME | 当前文件名。 |
FNR | 同NR,但相对于当前文件。 |
FS | 字段分隔符(默认是任何空格)。可以用户指定 |
IGNORECASE | 如果为真,则进行忽略大小写的匹配。 |
NF | 当前记录中的字段数。$NF指最后一个段内容 |
NR | 当前记录数。在文本中一般指多少行 |
OFMT | 数字的输出格式(默认值是%.6g)。 |
OFS | 输出字段分隔符(默认值是一个空格)。 |
ORS | 输出记录分隔符(默认值是一个换行符)。 |
RLENGTH | 由match函数所匹配的字符串的长度。 |
RS | 记录分隔符(默认是一个换行符)。 |
RSTART | 由match函数所匹配的字符串的第一个位置。 |
SUBSEP | 数组下标分隔符(默认值是\034)。 |
五、AWK内置操作符
= += -= *= /= %= ^= **= | 赋值 如a+=10代表a+10 |
?: | C条件表达式,a>b?a:b表示a大于b如为真返回a,如为假返回b |
|| | 逻辑或。只要一个为真即为真。 |
&& | 逻辑与。只要一个为假即为假。需两个同时为真才为真。 |
~ ~! | 匹配正则表达式和不匹配正则表达式。经常针对文本搜索 |
< <= > >= != == | 关系运算符 |
空格 | 连接 |
+ - | 加,减 |
* / & | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ *** | 求幂 |
++ -- | 增加或减少,作为前缀或后缀。这个一定要区分清楚++a与a++ |
$ | 字段引用 |
in | 数组成员 |
六、AWK元字符:\(转义字符)、^ $ [] | * + ?。其中+和?只能在AWK中使用不能再sed和grep中使用。+表示匹配一个或多个字符;?表示匹配0或1个字符。
相关阅读:
sed与awk常用功能 http://www.linuxidc.com/Linux/2013-06/86099.htm
Linux下shell编程常用grep\awk\sed语法 http://www.linuxidc.com/Linux/2013-07/87047.htm
Linux下Shell编程——awk编程 http://www.linuxidc.com/Linux/2013-06/85527.htm
文本处理工具awk详解 http://www.linuxidc.com/Linux/2013-05/84248.htm
Linux awk命令使用详解 http://www.linuxidc.com/Linux/2012-12/77082.htm
awk正则表达式和内置函数的使用方法实例详解
awk正则表达式及内置函数实例详解:
1、模糊匹配:
awk ‘{if($4!~/ufcx/) print $0}' data.f:如果第三项中不含ufcx有则打印
2、精确匹配:
awk ‘{if($5!=66)print $0}' data.f : 如果第五项不是66则打印
awk ‘{if($1>$5) print $0}' data.f:如果第一项大于第五项则打印
3、大小写匹配:
awk ‘/[Ss]ept/ {print $2}' data.f:符合,则打印第二字段
4、任意匹配:
awk ‘{if($4 ~/(lps|fcx)/) print $0}' data.f:第四个字段含有lps或fcx则输出
5、&&,||:
awk ‘{if($3 ~/a9/ || $2==”sept”) print $0}' data.f:一边为真则输出
6、变量定义:
awk ‘{date=$2;price=$5; if(date ~/[Ss]ept/) print “price is ” price}' data.f:变量定义,满足date是sept或者Sept的将price输出。
7、修改数值(源文件数值不变)
如果修改的是文本域,就要添加“”””。例如:awk ‘{if($2==”may”) $2=”tt”; print $0}' data.f
上边都是显示所有数据,awk ‘{if($2==”may”) {$2=”tt”; print $0}}' data.f这个只显示修改数据,仔细看看,其实语法和c一样,只是最外边添加了一个{}符号。
8、创建新域:(源文件数值不变)
或者awk ‘{if($5>$1){diff=$5-$1;print $1,diff}}' data.f
9、数据统计:
awk ‘{(total+=$5)}END{print total}' data.f:“{(total+=$5)}”和“{print
total}”代表两个不同的代码段,如果没有END每次的累积结果都会输出,END可以理解为代码段落的标志,这样只输出最终结果即{print
total}只执行一次。
10、统计文件大小:
11、Awk内置变量:
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行- F选项
NF 浏览记录的域个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
12、awk内置字符串处理函数
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
sprint ( f m t , exp )返回经f m t格式化后的exp
sub ( r, s ,$0) $0中s替换第一次r出现的位置
substr ( s , p )返回字符串s中从p开始的后缀部分
substr ( s , p , n )返回字符串s中从p开始长度为n的后缀部分
13、awk ‘gsub(/6\./,78) {print $0}' data.f:将所有“6.”换成78,并输出
awk ‘BEGIN{print index(“hello”,”lo”)}':输出的值为4
awk ‘{if($3==”3BC1997″) print length($3) ” ” $3}' data.f
awk ‘BEGIN{print match(“ABCD”,”B”)}':输出2
awk ‘BEGIN{print match(“ABCD”,/B/)}':“//”和“”””效果一样
awk ‘BEGIN {print split(“123#234#654″, myarray, “#”)}':返回数组元素个数,123#234#654是字符串,以“#”为分隔符,将字符串放入数组。
awk ‘{if($1==34) print substr($3,2,7)}' data.f
awk ‘BEGIN{print substr(“helloleeboy”,2,7)}':输出ellole
awk ‘BEGIN{print substr(“helloleeboy”,2,7)}' data.f:输出n遍ellole,n为data.f的行数
14、awk ‘BEGIN{print”May\tDay\n\nMay \104\141\171″}':\104\141\171表示Day。\t:tab键,\n:换行,\ddd:八进制
15、echo “65” | awk ‘{printf “%c\n”,$0}':printf函数,和c差不多,输出为A。(ASCII码)
echo “65” | awk ‘{printf “%d\n”,$0}':输出65数字。
awk ‘{printf “%-15s %s\n”,$2,$3}' data.f:“%-15s”左对齐15个字符长度
awk ‘{if(age<$1) print $0}' age=80 data.f和 awk ‘{age=49;if(age<$1) print $0}' data.f结果一样,前者将值传入awk,后者在awk中定义了一个变量。
1. awk简介
awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和 动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这 样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。下面介绍的awk是以GUN的gawk为例的,在 linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。
2. awk命令格式和选项
2.1. awk的语法有两种形式
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)
2.2. 命令选项
- -F fs or --field-separator fs
-
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
- -v var=value or --asign var=value
-
赋值一个用户定义变量。
- -f scripfile or --file scriptfile
-
从脚本文件中读取awk命令。
- -mf nnn and -mr nnn
-
对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
- -W compact or --compat, -W traditional or --traditional
-
在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
- -W copyleft or --copyleft, -W copyright or --copyright
-
打印简短的版权信息。
- -W help or --help, -W usage or --usage
-
打印全部awk选项和每个选项的简短说明。
- -W lint or --lint
-
打印不能向传统unix平台移植的结构的警告。
- -W lint-old or --lint-old
-
打印关于不能向传统unix平台移植的结构的警告。
- -W posix
-
打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。
- -W re-interval or --re-inerval
-
允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
- -W source program-text or --source program-text
-
使用program-text作为源代码,可与-f命令混用。
- -W version or --version
-
打印bug报告信息的版本。
3. 模式和操作
- awk脚本是由模式和操作组成的:
-
pattern {action} 如$ awk '/root/' test,或$ awk '$3 < 100' test。
两者是可选的,如果没有模式,则action应用到全部记录,如果没有action,则输出匹配全部记录。默认情况下,每一个输入行都是一条记录,但用户可通过RS变量指定不同的分隔符进行分隔。
3.1. 模式
模式可以是以下任意一个:
/正则表达式/:使用通配符的扩展集。
关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
END:让用户在最后一条输入记录被读取之后发生的动作。
3.2. 操作
操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。主要有四部份:
变量或数组赋值
输出命令
内置函数
控制流命令
4. awk的环境变量
Table 1. awk的环境变量
变量 | 描述 |
---|---|
$n | 当前记录的第n个字段,字段间由FS分隔。 |
$0 | 完整的输入记录。 |
ARGC | 命令行参数的数目。 |
ARGIND | 命令行中当前文件的位置(从0开始算)。 |
ARGV | 包含命令行参数的数组。 |
CONVFMT | 数字转换格式(默认值为%.6g) |
ENVIRON | 环境变量关联数组。 |
ERRNO | 最后一个系统错误的描述。 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔)。 |
FILENAME | 当前文件名。 |
FNR | 同NR,但相对于当前文件。 |
FS | 字段分隔符(默认是任何空格)。 |
IGNORECASE | 如果为真,则进行忽略大小写的匹配。 |
NF | 当前记录中的字段数。 |
NR | 当前记录数。 |
OFMT | 数字的输出格式(默认值是%.6g)。 |
OFS | 输出字段分隔符(默认值是一个空格)。 |
ORS | 输出记录分隔符(默认值是一个换行符)。 |
RLENGTH | 由match函数所匹配的字符串的长度。 |
RS | 记录分隔符(默认是一个换行符)。 |
RSTART | 由match函数所匹配的字符串的第一个位置。 |
SUBSEP | 数组下标分隔符(默认值是/034)。 |
5. awk运算符
Table 2. 运算符
运算符 | 描述 |
---|---|
= += -= *= /= %= ^= **= | 赋值 |
?: | C条件表达式 |
|| | 逻辑或 |
&& | 逻辑与 |
~ ~! | 匹配正则表达式和不匹配正则表达式 |
< <= > >= != == | 关系运算符 |
空格 | 连接 |
+ - | 加,减 |
* / & | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ *** | 求幂 |
++ -- | 增加或减少,作为前缀或后缀 |
$ | 字段引用 |
in | 数组成员 |
6. 记录和域
6.1. 记录
awk把每一个以换行符结束的行称为一个记录。
记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量ORS和RS中。
$0变量:它指的是整条记录。如$ awk '{print $0}' test将输出test文件中的所有记录。
变量NR:一个计数器,每处理完一条记录,NR的值就增加1。如$ awk '{print NR,$0}' test将输出test文件中所有记录,并在记录前显示记录号。
6.2. 域
记录中每个单词称做“域”,默认情况下以空格或tab分隔。awk可跟踪域的个数,并在内建变量NF中保存该值。如$ awk '{print $1,$3}' test将打印test文件中第一和第三个以空格分开的列(域)。
6.3. 域分隔符
内建变量FS保存输入域分隔符的值,默认是空格或tab。我们可以通过-F命令行选项修改FS的值。如$ awk -F: '{print $1,$5}' test将打印以冒号为分隔符的第一,第五列的内容。
可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk -F'[:/t]' '{print $1,$3}' test,表示以空格、冒号和tab作为分隔符。
输出域的分隔符默认是一个空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5间的逗号就是OFS的值。
7. gawk专用正则表达式元字符
一般通用的元字符集就不讲了,可参考我的Sed和Grep学习笔记。以下几个是gawk专用的,不适合unix版本的awk。
- /Y
-
匹配一个单词开头或者末尾的空字符串。
- /B
-
匹配单词内的空字符串。
- /<
-
匹配一个单词的开头的空字符串,锚定开始。
- />
-
匹配一个单词的末尾的空字符串,锚定末尾。
- /w
-
匹配一个字母数字组成的单词。
- /W
-
匹配一个非字母数字组成的单词。
- /‘
-
匹配字符串开头的一个空字符串。
- /'
-
匹配字符串末尾的一个空字符串。
8. POSIX字符集
可参考我的Grep学习笔记
9. 匹配操作符(~)
用来在记录或者域内匹配正则表达式。如$ awk '$1 ~/^root/' test将显示test文件第一列中以root开头的行。
10. 比较表达式
conditional expression1 ? expression2: expression3,例如:$ awk '{max = {$1 > $3} ? $1: $3: print max}' test。如果第一个域大于第三个域,$1就赋值给max,否则$3就赋值给max。
$ awk '$1 + $2 < 100' test。如果第一和第二个域相加大于100,则打印这些行。
$ awk '$1 > 5 && $2 < 10' test,如果第一个域大于5,并且第二个域小于10,则打印这些行。
11. 范围模板
范围模板匹配从第一个模板的第一次出现到第二个模板的第一次出现之间所有行。如果有一个模板没出现,则匹配到开头或末尾。如$ awk '/root/,/mysql/' test将显示root第一次出现到mysql第一次出现之间的所有行。
12. 一个验证passwd文件有效性的例子
$ cat /etc/passwd | awk -F: '/
NF != 7{/
printf("line %d,does not have 7 fields:%s/n",NR,$0)}/
$1 !~ /[A-Za-z0-9]/{printf("line %d,non alpha and numeric user id:%d: %s/n,NR,$0)}/
$2 == "*" {printf("line %d, no password: %s/n",NR,$0)}'
cat把结果输出给awk,awk把域之间的分隔符设为冒号。 |
|
如果域的数量(NF)不等于7,就执行下面的程序。 |
|
printf打印字符串"line ?? does not have 7 fields",并显示该条记录。 |
|
如果第一个域没有包含任何字母和数字,printf打印“no alpha and numeric user id" ,并显示记录数和记录。 |
|
如果第二个域是一个星号,就打印字符串“no passwd”,紧跟着显示记录数和记录本身。 |
13. 几个实例
$ awk '/^(no|so)/' test-----打印所有以模式no或so开头的行。
$ awk '/^[ns]/{print $1}' test-----如果记录以n或s开头,就打印这个记录。
$ awk '$1 ~/[0-9][0-9]$/(print $1}' test-----如果第一个域以两个数字结束就打印这个记录。
$ awk '$1 == 100 || $2 < 50' test-----如果第一个或等于100或者第二个域小于50,则打印该行。
$ awk '$1 != 10' test-----如果第一个域不等于10就打印该行。
$ awk '/test/{print $1 + 10}' test-----如果记录包含正则表达式test,则第一个域加10并打印出来。
$ awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test-----如果第一个域大于5则打印问号后面的表达式值,否则打印冒号后面的表达式值。
$ awk '/^root/,/^mysql/' test----打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。
14. awk编程
14.1. 变量
在awk中,变量不需要定义就可以直接使用,变量类型可以是数字或字符串。
赋值格式:Variable = expression,如$ awk '$1 ~/test/{count = $2 + $3; print count}' test,上式的作用是,awk先扫描第一个域,一旦test匹配,就把第二个域的值加上第三个域的值,并把结果赋值给变量count,最后打印出来。
awk 可以在命令行中给变量赋值,然后将这个变量传输给awk脚本。如$ awk -F: -f awkscript month=4 year=2004 test,上式的month和year都是自定义变量,分别被赋值为4和2004。在awk脚本中,这些变量使用起来就象是在脚本中建立的一样。注意,如果参数前面出现test,那么在BEGIN语句中的变量就不能被使用。
域变量也可被赋值和修改,如$ awk '{$2 = 100 + $1; print }' test,上式表示,如果第二个域不存在,awk将计算表达式100加$1的值,并将其赋值给$2,如果第二个域存在,则用表达式的值覆盖$2原来的值。再例如:$ awk '$1 == "root"{$1 ="test";print}' test,如果第一个域的值是“root”,则把它赋值为“test”,注意,字符串一定要用双引号。
内建变量的使用。变量列表在前面已列出,现在举个例子说明一下。$ awk -F: '{IGNORECASE=1; $1 == "MARY"{print NR,$1,$2,$NF}'test,把IGNORECASE设为1代表忽略大小写,打印第一个域是mary的记录数、第一个域、第二个域和最后一个域。
14.2. BEGIN模块
BEGIN 模块后紧跟着动作块,这个动作块在awk处理任何输入文件之前执行。所以它可以在没有任何输入的情况下进行测试。它通常用来改变内建变量的值,如OFS, RS和FS等,以及打印标题。如:$ awk 'BEGIN{FS=":"; OFS="/t"; ORS="/n/n"}{print $1,$2,$3} test。上式表示,在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。$ awk 'BEGIN{print "TITLE TEST"}只打印标题。
14.3. END模块
END不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处理完成后被执行。如$ awk 'END{print "The number of records is" NR}' test,上式将打印所有被处理的记录数。
14.4. 重定向和管道
awk 可使用shell的重定向符进行重定向输出,如:$ awk '$1 = 100 {print $1 > "output_file" }' test。上式表示如果第一个域的值等于100,则把它输出到output_file中。也可以用>>来重定向输出,但不清空文件,只做追加操作。
输出重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容,并给NF,NR和FNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就返回-1。如:
$ awk 'BEGIN{ "date" | getline d; print d}' test。执行linux的date命令,并通过管道输出给getline,然后再把输出赋值给自定义变量d,并打印它。
$ awk 'BEGIN{"date" | getline d; split(d,mon); print mon[2]}' test。执行shell的date命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给d,split函数把变量d转化成数组mon,然后打印数组mon的第二个元素。
$ awk 'BEGIN{while( "ls" | getline) print}',命令ls的输出传递给geline作为输入,循环使getline从ls的输出中读取一行,并把它打印到屏幕。这里没有输入文件,因为 BEGIN块在打开输入文件前执行,所以可以忽略输入文件。
$ awk 'BEGIN{printf "What is your name?"; getline name < "/dev/tty" } $1 ~name {print "Found" name on line ", NR "."} END{print "See you," name "."} test。在屏幕上打印”What is your name?",并等待用户应答。当一行输入完毕后,getline函数从终端接收该行输入,并把它储存在自定义变量name中。如果第一个域匹配变量 name的值,print函数就被执行,END块打印See you和name的值。
$ awk 'BEGIN{while (getline < "/etc/passwd" > 0) lc++; print lc}'。awk将逐行读取文件/etc/passwd的内容,在到达文件末尾前,计数器lc一直增加,当到末尾时,打印lc的值。注意,如果文件不存在,getline返回-1,如果到达文件的末尾就返回0,如果读到一行,就返回1,所以命令 while (getline < "/etc/passwd")在文件不存在的情况下将陷入无限循环,因为返回-1表示逻辑真。
可以在awk中打开一个管道,且同一时刻只能有一个管道存在。通过close()可关闭管道。如:$ awk '{print $1, $2 | "sort" }' test END {close("sort")}。awd把print语句的输出通过管道作为linux命令sort的输入,END块执行关闭管道操作。
system函数可以在awk中执行linux的命令。如:$ awk 'BEGIN{system("clear")'。
fflush函数用以刷新输出缓冲区,如果没有参数,就刷新标准输出的缓冲区,如果以空字符串为参数,如fflush(""),则刷新所有文件和管道的输出缓冲区。
14.5. 条件语句
awk中的条件语句是从C语言中借鉴过来的,可控制程序的流程。
14.5.1. if语句
格式: {if (expression){ statement; statement; ... } }
$ awk '{if ($1 <$2) print $2 "too high"}' test。如果第一个域小于第二个域则打印。
$ awk '{if ($1 < $2) {count++; print "ok"}}' test.如果第一个域小于第二个域,则count加一,并打印ok。
14.5.2. if/else语句,用于双重判断。
格式: {if (expression){ statement; statement; ... } else{ statement; statement; ... } }
$ awk '{if ($1 > 100) print $1 "bad" ; else print "ok"}' test。如果$1大于100则打印$1 bad,否则打印ok。
$ awk '{if ($1 > 100){ count++; print $1} else {count--; print $2}' test。如果$1大于100,则count加一,并打印$1,否则count减一,并打印$1。
14.5.3. if/else else if语句,用于多重判断。
格式: {if (expression){ statement; statement; ... } else if (expression){ statement; statement; ... } else if (expression){ statement; statement; ... } else { statement; statement; ... } }
14.6. 循环
awk有三种循环:while循环;for循环;special for循环。
$ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。变量的初始值为1,若i小于可等于NF(记录中域的个数),则执行打印语句,且i增加1。直到i的值大于NF.
$ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。
breadkcontinue语句。break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端。如:
{for ( x=3; x<=NF; x++) if ($x<0){print "Bottomed out!"; break}}{for ( x=3; x<=NF; x++) if ($x==0){print "Get next item"; continue}}
next语句从输入文件中读取一行,然后从头开始执行awk脚本。如:
{if ($1 ~/test/){next} else {print}}
exit语句用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。
14.7. 数组
awk中的数组的下标可以是数字和字母,称为关联数组。
14.7.1. 下标与关联数组
用变量作为数组下标。如:$ awk {name[x++]=$2};END{for(i=0;i<NR;i++) print i,name[i]}' test。数组name中的下标是一个自定义变量x,awk初始化x的值为0,在每次使用后增加1。第二个域的值被赋给name数组的各个元素。在END 模块中,for循环被用于循环整个数组,从下标为0的元素开始,打印那些存储在数组中的值。因为下标是关健字,所以它不一定从0开始,可以从任何值开始。
special for循环用于读取关联数组中的元素。格式如下:
{for (item in arrayname){ print arrayname[item] }}
$ awk '/^tom/{name[NR]=$1}; END{for(i in name){print name[i]}}' test。打印有值的数组元素。打印的顺序是随机的。
用字符串作为下标。如:count["test"]
用域值作为数组的下标。一种新的for循环方式,for (index_value in array) statement。如:$ awk '{count[$1]++} END{for(name in count) print name,count[name]}' test。该语句将打印$1中字符串出现的次数。它首先以第一个域作数组count的下标,第一个域变化,索引就变化。
delete 函数用于删除数组元素。如:$ awk '{line[x++]=$1} END{for(x in line) delete(line[x])}' test。分配给数组line的是第一个域的值,所有记录处理完成后,special for循环将删除每一个元素。
14.8. awk的内建函数
14.8.1. 字符串函数
sub函数匹配记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配的时候。格式如下:
sub (regular expression, substitution string): sub (regular expression, substitution string, target string)
实例:
$ awk '{ sub(/test/, "mytest"); print }' testfile $ awk '{ sub(/test/, "mytest"); $1}; print }' testfile
第一个例子在整个记录中匹配,替换只发生在第一次匹配发生的时候。如要在整个文件中进行匹配需要用到gsub
第二个例子在整个记录的第一个域中进行匹配,替换只发生在第一次匹配发生的时候。
gsub函数作用如sub,但它在整个文档中进行匹配。格式如下:
gsub (regular expression, substitution string) gsub (regular expression, substitution string, target string)
实例:
$ awk '{ gsub(/test/, "mytest"); print }' testfile $ awk '{ gsub(/test/, "mytest"), $1 }; print }' testfile
第一个例子在整个文档中匹配test,匹配的都被替换成mytest。
第二个例子在整个文档的第一个域中匹配,所有匹配的都被替换成mytest。
index函数返回子字符串第一次被匹配的位置,偏移量从位置1开始。格式如下:
index(string, substring)
实例:
$ awk '{ print index("test", "mytest") }' testfile
实例返回test在mytest的位置,结果应该是3。
length函数返回记录的字符数。格式如下:
length( string ) length
实例:
$ awk '{ print length( "test" ) }' $ awk '{ print length }' testfile
第一个实例返回test字符串的长度。
第二个实例返回testfile文件中第条记录的字符数。
substr函数返回从位置1开始的子字符串,如果指定长度超过实际长度,就返回整个字符串。格式如下:
substr( string, starting position ) substr( string, starting position, length of string )
实例:
$ awk '{ print substr( "hello world", 7,11 ) }'
上例截取了world子字符串。
match函数返回在字符串中正则表达式位置的索引,如果找不到指定的正则表达式则返回0。match函数会设置内建变量RSTART为字符串中子字符串的开始位置,RLENGTH为到子字符串末尾的字符个数。substr可利于这些变量来截取字符串。函数格式如下:
match( string, regular expression )
实例:
$ awk '{start=match("this is a test",/[a-z]+$/); print start}' $ awk '{start=match("this is a test",/[a-z]+$/); print start, RSTART, RLENGTH }'
第一个实例打印以连续小写字符结尾的开始位置,这里是11。
第二个实例还打印RSTART和RLENGTH变量,这里是11(start),11(RSTART),4(RLENGTH)。
toupper和tolower函数可用于字符串大小间的转换,该功能只在gawk中有效。格式如下:
toupper( string ) tolower( string )
实例:
$ awk '{ print toupper("test"), tolower("TEST") }'
split函数可按给定的分隔符把字符串分割为一个数组。如果分隔符没提供,则按当前FS值进行分割。格式如下:
split( string, array, field separator ) split( string, array )
实例:
$ awk '{ split( "20:18:00", time, ":" ); print time[2] }'
上例把时间按冒号分割到time数组内,并显示第二个数组元素18。
14.8.2. 时间函数
systime函数返回从1970年1月1日开始到当前时间(不计闰年)的整秒数。格式如下:
systime()
实例:
$ awk '{ now = systime(); print now }'
strftime函数使用C库中的strftime函数格式化时间。格式如下:
systime( [format specification][,timestamp] )
Table 3. 日期和时间格式说明符
格式 描述 %a 星期几的缩写(Sun) %A 星期几的完整写法(Sunday) %b 月名的缩写(Oct) %B 月名的完整写法(October) %c 本地日期和时间 %d 十进制日期 %D 日期 08/20/99 %e 日期,如果只有一位会补上一个空格 %H 用十进制表示24小时格式的小时 %I 用十进制表示12小时格式的小时 %j 从1月1日起一年中的第几天 %m 十进制表示的月份 %M 十进制表示的分钟 %p 12小时表示法(AM/PM) %S 十进制表示的秒 %U 十进制表示的一年中的第几个星期(星期天作为一个星期的开始) %w 十进制表示的星期几(星期天是0) %W 十进制表示的一年中的第几个星期(星期一作为一个星期的开始) %x 重新设置本地日期(08/20/99) %X 重新设置本地时间(12:00:00) %y 两位数字表示的年(99) %Y 当前月份 %Z 时区(PDT) %% 百分号(%) 实例:
$ awk '{ now=strftime( "%D", systime() ); print now }' $ awk '{ now=strftime("%m/%d/%y"); print now }'
14.8.3. 内建数学函数
Table 4.
函数名称 | 返回值 |
---|---|
atan2(x,y) | y,x范围内的余切 |
cos(x) | 余弦函数 |
exp(x) | 求幂 |
int(x) | 取整 |
log(x) | 自然对数 |
rand() | 随机数 |
sin(x) | 正弦 |
sqrt(x) | 平方根 |
srand(x) | x是rand()函数的种子 |
int(x) | 取整,过程没有舍入 |
rand() | 产生一个大于等于0而小于1的随机数 |
14.8.4. 自定义函数
在awk中还可自定义函数,格式如下:
function name ( parameter, parameter, parameter, ... ) { statements return expression # the return statement and expression are optional }
15. How-to
如何把一行竖排的数据转换成横排?
awk '{printf("%s,",$1)}' filename
awk 正则表达式的更多相关文章
- 学习笔记之Shell脚本学习指南 & sed与awk & 正则表达式
正则表达式_百度百科 http://baike.baidu.com/link?url=ybgDrN2WQQKN64_gu-diCqdeDqL8LQ-jiQ-ftzzPaNUa9CmgBRDNnyx50 ...
- awk 正则表达式、正则运算符详细介绍
前言:使用awk作为文本处理工具,正则表达式是少不了的. 要掌握这个工具的正则表达式使用.其实,我们不必单独去学习它的正则表达式.正则表达式就像一门程序语言,有自己语法规则已经表示意思. 对于不同工具 ...
- linux 三大利器 grep sed awk 正则表达式
正则表达式目标 正则表达式单字符: 特定字符 范围字符:单个字符[ ] :代表查找单个字符,括号内为字符范围 数字字符:[0-9],[259] 查找 0~9 和 2.5 .9 中的任意一个字符 小写字 ...
- linux(5)--补充(管道| / 重定向> / xargs)/find 与xargs结合使用/vi,grep,sed,awk(支持正则表达式的工具程序)
本节中正则表达式的工具程序 grep,sed和awk是重点,也是难点!!! 先补充一下一. 管道| / 重定向> / xargs 如:1. 管道和重定向的区别:具体可以见 http://www. ...
- awk命令速查
awk与sed.grep一样都是为了加工数据流而做成的文本加工过滤器命令.awk会事先把输入的数据根据字段单位进行分割.在没有制定分割单位的情况下,以输入数据中的空格或Tab为分隔符.与sed相比,它 ...
- awk sed 总结
Awk总结笔记 介绍 90年代 new awk :nawk Linux 的是gawk 我们简化awk 用法 # awk [options ] ‘scripts’ file1 file2 .... # ...
- Linux下Awk详解(转载)
什么是Awk Awk是一种小巧的编程语言及命令行工具.(其名称得自于它的创始人Alfred Aho.Peter Weinberger 和 Brian Kernighan姓氏的首个字母).它非常适合服务 ...
- 【转】Linux强大命令 Awk 20分钟入门介绍
什么是Awk Awk是一种小巧的编程语言及命令行工具.(其名称得自于它的创始人Alfred Aho.Peter Weinberger 和 Brian Kernighan姓氏的首个字母).它非常适合服务 ...
- Linux实战教学笔记18:linux三剑客之awk精讲
Linux三剑客之awk精讲(基础与进阶) 标签(空格分隔): Linux实战教学笔记-陈思齐 快捷跳转目录: * 第1章:awk基础入门 * 1.1:awk简介 * 1.2:学完awk你可以掌握: ...
随机推荐
- JProtector 帮助文档
一.应用加密 1.使用 JProtector在线 进行应用加密:使用浏览器访问 http://app.shuton.net/encryptjar, 点击 Browse 选择待加密的应用jar包.war ...
- 转:Bootstrap研究 精巧的网格布局系统
本网格布局系统属于Scaffolding(框架,布局)部分.在Scaffolding里面有(固定)网格布局(Grid System)和流式网格布局(Fluid Grid System).本文讨论第一种 ...
- uva 10271 Chopsticks(dp)
题目连接:10271 - Chopsticks 题目大意:给出m和n, 然后给出n根筷子从小到大给出, 现在要从这n根筷子中选出m + 8组筷子, 每组筷子包括三根, 现在要求所有m + 8组每组筷子 ...
- Ubuntu 12.04 (10) Personal Environment - @staticor
Chinese Input ================= I use Wubu, so Fcitx, sudo add-apt-repository ppa:fcitx-team/nightly ...
- C#后台代码编写图片地址Properties.Resources._1;
if (i == 0) { pictureBox1.Image = Properties.Resources._1; ...
- android的animator
3.0 以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这 ...
- python 3.4 装matplotlib numpy
为了装个matplotlib包,搞了好久: python3.4,官方没有对应版本的包,只能去下面这个地方下对应的版本: http://www.lfd.uci.edu/~gohlke/pythonl ...
- 在Delphi中开发使用多显示器的应用程序(MonitorCount和DefaultMonitor)
Windows可以将多个显示器映射为虚拟桌面,使我们可以利用这一点设计出方便工作的应用程序.例如PowerPoint就充分发挥了双显示器的优势(大多数的笔记本电脑都支持),它可以在一个显示器上播放幻灯 ...
- The Apache™ Batik Project
Apache(tm) Batik SVG Toolkit - a Java-based toolkit for applications or applets that want to use ima ...
- Linux下安装配置词典GoldenDict
GoldenDict apt-get install goldendict 安装完成以后,需要自己手动加入字典,增加在线翻译网址(例如,有道,金山等),点击 编辑--dictionaries 完 ...