@ -1,4 +1,5 @@
awk
# awk
===
===
文本和数据进行处理的编程语言
文本和数据进行处理的编程语言
@ -9,19 +10,19 @@ awk
## awk命令格式和选项
## awk命令格式和选项
** 语法形式**
### 语法形式
```
```sh
awk [options] 'script' var=value file(s)
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)
awk [options] -f scriptfile var=value file(s)
```
```
** 常用命令选项**
### 常用命令选项
* ** -F fs ** fs指定输入分隔符, fs可以是字符串或正则表达式, 如-F:
***-F fs * ** fs指定输入分隔符, fs可以是字符串或正则表达式, 如-F:
* ** -v var=value ** 赋值一个用户定义变量, 将外部变量传递给awk
***-v var=value * ** 赋值一个用户定义变量, 将外部变量传递给awk
* ** -f scripfile ** 从脚本文件中读取awk命令
***-f scripfile * ** 从脚本文件中读取awk命令
* ** -m[fr] val ** 对val值设置内在限制, -mf选项限制分配给val的最大块数目; -mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能, 在标准awk中不适用。
***-m[fr] val * ** 对val值设置内在限制, -mf选项限制分配给val的最大块数目; -mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能, 在标准awk中不适用。
## awk模式和操作
## awk模式和操作
@ -33,7 +34,7 @@ awk脚本是由模式和操作组成的。
* /正则表达式/:使用通配符的扩展集。
* /正则表达式/:使用通配符的扩展集。
* 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
* 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
* 模式匹配表达式:用运算符`~`(匹配)和`! ~`(不匹配)。
* 模式匹配表达式:用运算符`~`(匹配)和`~! `(不匹配)。
* BEGIN语句块、pattern语句块、END语句块: 参见awk的工作原理
* BEGIN语句块、pattern语句块、END语句块: 参见awk的工作原理
### 操作
### 操作
@ -47,20 +48,20 @@ awk脚本是由模式和操作组成的。
## awk脚本基本结构
## awk脚本基本结构
```
```sh
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
```
```
一个awk脚本通常由: BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成, 这三个部分是可选的。任意一个部分都可以不出现在脚本中, 脚本通常是被** 单引号** 或** 双引号** 中,例如:
一个awk脚本通常由: BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成, 这三个部分是可选的。任意一个部分都可以不出现在脚本中, 脚本通常是被** 单引号** 或** 双引号** 中,例如:
```
```sh
awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename
```
```
### awk的工作原理
### awk的工作原理
```
```sh
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
```
```
@ -74,9 +75,9 @@ awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
**pattern语句块** 中的通用命令是最重要的部分, 它也是可选的。如果没有提供pattern语句块, 则默认执行`{ print }`, 即打印每一个读取到的行, awk读取的每一行都会执行该语句块。
**pattern语句块** 中的通用命令是最重要的部分, 它也是可选的。如果没有提供pattern语句块, 则默认执行`{ print }`, 即打印每一个读取到的行, awk读取的每一行都会执行该语句块。
** 示例**
### 示例
```
```sh
echo -e "A line 1nA line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
echo -e "A line 1nA line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
Start
Start
A line 1
A line 1
@ -86,14 +87,14 @@ End
当使用不带参数的`print`时,它就打印当前行,当`print`的参数是以逗号进行分隔时, 打印时则以空格作为定界符。在awk的print语句块中双引号是被当作拼接符使用, 例如:
当使用不带参数的`print`时,它就打印当前行,当`print`的参数是以逗号进行分隔时, 打印时则以空格作为定界符。在awk的print语句块中双引号是被当作拼接符使用, 例如:
```
```sh
echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }'
echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }'
v1 v2 v3
v1 v2 v3
```
```
双引号拼接使用:
双引号拼接使用:
```
```sh
echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }'
echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }'
v1=v2=v3
v1=v2=v3
```
```
@ -104,7 +105,7 @@ v1=v2=v3
说明:[A][N][P][G]表示第一个支持变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk
说明:[A][N][P][G]表示第一个支持变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk
```
```sh
** $n**当前记录的第n个字段, 比如n为1表示第一个字段, n为2表示第二个字段。
** $n**当前记录的第n个字段, 比如n为1表示第一个字段, n为2表示第二个字段。
** $0**这个变量包含执行过程中当前行的文本内容。
** $0**这个变量包含执行过程中当前行的文本内容。
[N]**ARGC**命令行参数的数目。
[N]**ARGC**命令行参数的数目。
@ -129,9 +130,64 @@ v1=v2=v3
[N]**SUBSEP**数组下标分隔符( 默认值是34) 。
[N]**SUBSEP**数组下标分隔符( 默认值是34) 。
```
```
** 示例**
示例
FS示例
```sh
awk FS变量用于设置每个记录的字段分割符, 其可以设置为任何单个字符或者正则表达式
FS可以更改任意次数, 会保留其值直到明确更改, 如果想更改字段分割符, 在阅读行之前更改, 固此改变会影响阅读的内容
awk -F 'FS''命令'文件名
或
awk 'BEGIN {FS="FS";}'
用于读取具有:作为字段分割符的/etc/passwd文件:awk -f etc_pass.awk /etc/passwd
BEGIN{
FS = ":";
print "\tUserID\tGroupID\tHomeDirectory";
}
{
print $1"\t"$3"\t"$4"\t"$6;
}
END{
print NR,"打印记录"
#NR 统计打印的数目
}
awk OFS是awk FS变量的输出, 默认情况, awk OFS是单个空格字符
awk -F ':' '{print $3,$4;}' /etc/passwd
打印语句中的:,默认情况下两个参数连接为一个空间, 该空间是awk OFS的值, 固其值被插入到输出中的字段之间
awk -F ':' 'BEGIN{OFS ="=";}{print $3,$4;}' /etc/passwd
```
```
awk RS示例: 记录分割符变量
```sh
awk RS定义了一条线, awk默认逐行读取。将信息存储在一个文件中, 每个记录由两个新行隔开, 每个字段用一个新行分割
打印姓名和第二行数字
cat student.awk
BEGIN {
RS =“\ n \ n”;;
FS = “\ n”个;
}
{
print $ 1, $ 2;
}
awk -f student.awk student.txt
```
```sh
echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
@ -140,13 +196,13 @@ Line No:3, No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7
使用`print $NF`可以打印出一行中的最后一个字段,使用`$(NF-1)`则是打印倒数第二个字段,其他以此类推:
使用`print $NF`可以打印出一行中的最后一个字段,使用`$(NF-1)`则是打印倒数第二个字段,其他以此类推:
```
```sh
echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $NF}'
echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $NF}'
f3
f3
f5
f5
```
```
```
```sh
echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $(NF-1)}'
echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $(NF-1)}'
f2
f2
f4
f4
@ -155,13 +211,13 @@ f4
打印每一行的第二和第三个字段:
打印每一行的第二和第三个字段:
```
```sh
awk '{ print $2,$3 }' filename
awk '{ print $2,$3 }' filename
```
```
统计文件中的行数:
统计文件中的行数:
```
```sh
awk 'END{ print NR }' filename
awk 'END{ print NR }' filename
```
```
@ -169,7 +225,7 @@ awk 'END{ print NR }' filename
一个每一行中第一个字段值累加的例子:
一个每一行中第一个字段值累加的例子:
```
```sh
seq 5 | awk 'BEGIN{ sum=0; print "总和:" } { print $1"+"; sum+=$1 } END{ print "等于"; print sum }'
seq 5 | awk 'BEGIN{ sum=0; print "总和:" } { print $1"+"; sum+=$1 } END{ print "等于"; print sum }'
总和:
总和:
1+
1+
@ -185,14 +241,14 @@ seq 5 | awk 'BEGIN{ sum=0; print "总和:" } { print $1"+"; sum+=$1 } END{ pri
借助** `-v` 选项** , 可以将外部值( 并非来自stdin) 传递给awk:
借助** `-v` 选项** , 可以将外部值( 并非来自stdin) 传递给awk:
```
```sh
VAR=10000
VAR=10000
echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
```
```
另一种传递外部变量方法:
另一种传递外部变量方法:
```
```sh
var1="aaa"
var1="aaa"
var2="bbb"
var2="bbb"
echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
@ -200,7 +256,7 @@ echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
当输入来自于文件时使用:
当输入来自于文件时使用:
```
```sh
awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename
awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename
```
```
@ -208,13 +264,13 @@ awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename
## 查找进程pid
## 查找进程pid
```
```sh
netstat -antup | grep 7770 | awk '{ print $NF NR}' | awk '{ print $1}'
netstat -antup | grep 7770 | awk '{ print $NF NR}' | awk '{ print $1}'
```
```
## awk运算与判断
## awk运算与判断
作为一种程序设计语言所应具有的特点之一, awk支持多种运算, 这些运算与C语言提供的基本相同。awk还提供了一系列内置的运算函数( 如log、sqr、cos、sin等) 和一些用于对字符串进行操作( 运算) 的函数( 如length、substr等等) 。这些函数的引用大大的提高了awk的运算功能。作为对条件转移指令的一部分, 关系判断是每种程序设计语言都具备的功能, awk也不例外, awk中允许进行多种测试, 作为样式匹配, 还提供了模式匹配表达式~(匹配)和! ~( 不匹配) 。作为对测试的一种扩充, awk也支持用逻辑运算符。
作为一种程序设计语言所应具有的特点之一, awk支持多种运算, 这些运算与C语言提供的基本相同。awk还提供了一系列内置的运算函数( 如log、sqr、cos、sin等) 和一些用于对字符串进行操作( 运算) 的函数( 如length、substr等等) 。这些函数的引用大大的提高了awk的运算功能。作为对条件转移指令的一部分, 关系判断是每种程序设计语言都具备的功能, awk也不例外, awk中允许进行多种测试, 作为样式匹配, 还提供了模式匹配表达式~(匹配)和~! ( 不匹配) 。作为对测试的一种扩充, awk也支持用逻辑运算符。
### 算术运算符
### 算术运算符
@ -228,7 +284,7 @@ netstat -antup | grep 7770 | awk '{ print $NF NR}' | awk '{ print $1}'
例:
例:
```
```sh
awk 'BEGIN{a="b";print a++,++a;}'
awk 'BEGIN{a="b";print a++,++a;}'
0 2
0 2
```
```
@ -243,7 +299,7 @@ awk 'BEGIN{a="b";print a++,++a;}'
例:
例:
```
```sh
a+=5; 等价于: a=a+5; 其它同类
a+=5; 等价于: a=a+5; 其它同类
```
```
@ -256,7 +312,7 @@ a+=5; 等价于: a=a+5; 其它同类
例:
例:
```
```sh
awk 'BEGIN{a=1;b=2;print (a>5 & & b< =2),(a>5 || b< =2);}'
awk 'BEGIN{a=1;b=2;print (a>5 & & b< =2),(a>5 || b< =2);}'
0 1
0 1
```
```
@ -265,11 +321,11 @@ awk 'BEGIN{a=1;b=2;print (a>5 && b<=2),(a>5 || b<=2);}'
| 运算符 | 描述 |
| 运算符 | 描述 |
| ----- | ---- |
| ----- | ---- |
| ~ ! ~ | 匹配正则表达式和不匹配正则表达式 |
| ~ ~! | 匹配正则表达式和不匹配正则表达式 |
例:
例:
```
```sh
awk 'BEGIN{a="100testa";if(a ~ /^100*/){print "ok";}}'
awk 'BEGIN{a="100testa";if(a ~ /^100*/){print "ok";}}'
ok
ok
```
```
@ -282,7 +338,7 @@ ok
例:
例:
```
```sh
awk 'BEGIN{a=11;if(a >= 9){print "ok";}}'
awk 'BEGIN{a=11;if(a >= 9){print "ok";}}'
ok
ok
```
```
@ -300,17 +356,17 @@ ok
例:
例:
```
```sh
awk 'BEGIN{a="b";print a=="b"?"ok":"err";}'
awk 'BEGIN{a="b";print a=="b"?"ok":"err";}'
ok
ok
```
```
```
```sh
awk 'BEGIN{a="b";arr[0]="b";arr[1]="c";print (a in arr);}'
awk 'BEGIN{a="b";arr[0]="b";arr[1]="c";print (a in arr);}'
0
0
```
```
```
```sh
awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print (a in arr);}'
awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print (a in arr);}'
1
1
```
```
@ -326,7 +382,7 @@ awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print (a in arr);}'
awk中`next`语句使用: 在循环逐行匹配, 如果遇到next, 就会跳过当前行, 直接忽略下面语句。而进行下一行匹配。next语句一般用于多行合并:
awk中`next`语句使用: 在循环逐行匹配, 如果遇到next, 就会跳过当前行, 直接忽略下面语句。而进行下一行匹配。next语句一般用于多行合并:
```
```sh
cat text.txt
cat text.txt
a
a
b
b
@ -343,7 +399,7 @@ awk 'NR%2==1{next}{print NR,$0;}' text.txt
分析发现需要将包含有“web”行进行跳过, 然后需要将内容与下面行合并为一行:
分析发现需要将包含有“web”行进行跳过, 然后需要将内容与下面行合并为一行:
```
```sh
cat text.txt
cat text.txt
web01[192.168.2.100]
web01[192.168.2.100]
httpdok
httpdok
@ -381,19 +437,19 @@ awk getline从整体上来说, 用法说明:
执行linux的`date`命令,并通过管道输出给`getline`, 然后再把输出赋值给自定义变量out, 并打印它:
执行linux的`date`命令,并通过管道输出给`getline`, 然后再把输出赋值给自定义变量out, 并打印它:
```
```sh
awk 'BEGIN{ "date" | getline out; print out }' test
awk 'BEGIN{ "date" | getline out; print out }' test
```
```
执行shell的date命令, 并通过管道输出给getline, 然后getline从管道中读取并将输入赋值给out, split函数把变量out转化成数组mon, 然后打印数组mon的第二个元素:
执行shell的date命令, 并通过管道输出给getline, 然后getline从管道中读取并将输入赋值给out, split函数把变量out转化成数组mon, 然后打印数组mon的第二个元素:
```
```sh
awk 'BEGIN{ "date" | getline out; split(out,mon); print mon[2] }' test
awk 'BEGIN{ "date" | getline out; split(out,mon); print mon[2] }' test
```
```
命令ls的输出传递给geline作为输入, 循环使getline从ls的输出中读取一行, 并把它打印到屏幕。这里没有输入文件, 因为BEGIN块在打开输入文件前执行, 所以可以忽略输入文件。
命令ls的输出传递给geline作为输入, 循环使getline从ls的输出中读取一行, 并把它打印到屏幕。这里没有输入文件, 因为BEGIN块在打开输入文件前执行, 所以可以忽略输入文件。
```
```sh
awk 'BEGIN{ while( "ls" | getline) print }'
awk 'BEGIN{ while( "ls" | getline) print }'
```
```
@ -401,7 +457,7 @@ awk 'BEGIN{ while( "ls" | getline) print }'
awk中允许在程序中关闭一个输入或输出文件, 方法是使用awk的close语句。
awk中允许在程序中关闭一个输入或输出文件, 方法是使用awk的close语句。
```
```sh
close("filename")
close("filename")
```
```
@ -411,7 +467,7 @@ filename可以是getline打开的文件, 也可以是stdin, 包含文件名的
awk中允许用如下方式将结果输出到一个文件:
awk中允许用如下方式将结果输出到一个文件:
```
```sh
echo | awk '{printf("hello word!n") > "datafile"}'
echo | awk '{printf("hello word!n") > "datafile"}'
或
或
echo | awk '{printf("hello word!n") >> "datafile"}'
echo | awk '{printf("hello word!n") >> "datafile"}'
@ -421,7 +477,7 @@ echo | awk '{printf("hello word!n") >> "datafile"}'
默认的字段定界符是空格,可以使用`-F "定界符"`明确指定一个定界符:
默认的字段定界符是空格,可以使用`-F "定界符"`明确指定一个定界符:
```
```sh
awk -F: '{ print $NF }' /etc/passwd
awk -F: '{ print $NF }' /etc/passwd
或
或
awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
@ -435,7 +491,7 @@ awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
### 条件判断语句
### 条件判断语句
```
```sh
if(表达式)
if(表达式)
语句1
语句1
else
else
@ -444,7 +500,7 @@ else
格式中语句1可以是多个语句, 为了方便判断和阅读, 最好将多个语句用{}括起来。awk分枝结构允许嵌套, 其格式为:
格式中语句1可以是多个语句, 为了方便判断和阅读, 最好将多个语句用{}括起来。awk分枝结构允许嵌套, 其格式为:
```
```sh
if(表达式)
if(表达式)
{语句1}
{语句1}
else if(表达式)
else if(表达式)
@ -455,7 +511,7 @@ else
示例:
示例:
```
```sh
awk 'BEGIN{
awk 'BEGIN{
test=100;
test=100;
if(test>90){
if(test>90){
@ -478,14 +534,14 @@ very good
#### while语句
#### while语句
```
```sh
while(表达式)
while(表达式)
{语句}
{语句}
```
```
示例:
示例:
```
```sh
awk 'BEGIN{
awk 'BEGIN{
test=100;
test=100;
total=0;
total=0;
@ -504,14 +560,14 @@ for循环有两种格式:
格式1:
格式1:
```
```sh
for(变量 in 数组)
for(变量 in 数组)
{语句}
{语句}
```
```
示例:
示例:
```
```sh
awk 'BEGIN{
awk 'BEGIN{
for(k in ENVIRON){
for(k in ENVIRON){
print k"="ENVIRON[k];
print k"="ENVIRON[k];
@ -532,14 +588,14 @@ SSH_CLIENT=192.168.1.21 53087 22
格式2:
格式2:
```
```sh
for(变量;条件;表达式)
for(变量;条件;表达式)
{语句}
{语句}
```
```
示例:
示例:
```
```sh
awk 'BEGIN{
awk 'BEGIN{
total=0;
total=0;
for(i=0;i< =100;i++){
for(i=0;i< =100;i++){
@ -552,14 +608,14 @@ print total;
#### do循环
#### do循环
```
```sh
do
do
{语句} while(条件)
{语句} while(条件)
```
```
例子:
例子:
```
```sh
awk 'BEGIN{
awk 'BEGIN{
total=0;
total=0;
i=0;
i=0;
@ -584,14 +640,14 @@ do {total+=i;i++;} while(i<=100)
数字做数组索引(下标):
数字做数组索引(下标):
```
```sh
Array[1]="sun"
Array[1]="sun"
Array[2]="kai"
Array[2]="kai"
```
```
字符串做数组索引(下标):
字符串做数组索引(下标):
```
```sh
Array["first"]="www"
Array["first"]="www"
Array"[last"]="name"
Array"[last"]="name"
Array["birth"]="1987"
Array["birth"]="1987"
@ -601,7 +657,7 @@ Array["birth"]="1987"
** 读取数组的值**
** 读取数组的值**
```
```sh
{ for(item in array) {print array[item]}; } #输出的顺序是随机的
{ for(item in array) {print array[item]}; } #输出的顺序是随机的
{ for(i=1;i< =len;i++) {print array[i]}; } #Len 是数组的长度
{ for(i=1;i< =len;i++) {print array[i]}; } #Len 是数组的长度
```
```
@ -610,14 +666,14 @@ Array["birth"]="1987"
** 得到数组长度:**
** 得到数组长度:**
```
```sh
awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA),lens;}'
awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA),lens;}'
4 4
4 4
```
```
length返回字符串以及数组长度, split进行分割字符串为数组, 也会返回分割得到数组长度。
length返回字符串以及数组长度, split进行分割字符串为数组, 也会返回分割得到数组长度。
```
```sh
awk 'BEGIN{info="it is a test";split(info,tA," ");print asort(tA);}'
awk 'BEGIN{info="it is a test";split(info,tA," ");print asort(tA);}'
4
4
```
```
@ -626,7 +682,7 @@ asort对数组进行排序, 返回数组长度。
** 输出数组内容(无序,有序输出):**
** 输出数组内容(无序,有序输出):**
```
```sh
awk 'BEGIN{info="it is a test";split(info,tA," ");for(k in tA){print k,tA[k];}}'
awk 'BEGIN{info="it is a test";split(info,tA," ");for(k in tA){print k,tA[k];}}'
4 test
4 test
1 it
1 it
@ -636,7 +692,7 @@ awk 'BEGIN{info="it is a test";split(info,tA," ");for(k in tA){print k,tA[k];}}'
`for…in` 输出,因为数组是关联数组,默认是无序的。所以通过`for…in`得到是无序的数组。如果需要得到有序数组,需要通过下标获得。
`for…in` 输出,因为数组是关联数组,默认是无序的。所以通过`for…in`得到是无序的数组。如果需要得到有序数组,需要通过下标获得。
```
```sh
awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k< =tlen;k++){print k,tA[k];}}'
awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k< =tlen;k++){print k,tA[k];}}'
1 it
1 it
2 is
2 is
@ -648,7 +704,7 @@ awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k<=tlen;k++){prin
** 判断键值存在以及删除键值:**
** 判断键值存在以及删除键值:**
```
```sh
#错误的判断方法:
#错误的判断方法:
awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";if(tB["c"]!="1"){print "no found";};for(k in tB){print k,tB[k];}}'
awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";if(tB["c"]!="1"){print "no found";};for(k in tB){print k,tB[k];}}'
no found
no found
@ -738,10 +794,9 @@ awk内置函数, 主要分以下3种类似: 算数函数、字符串函数、
| rand( ) | 返回任意数字 n, 其中 0 < = n < 1 。 |
| rand( ) | 返回任意数字 n, 其中 0 < = n < 1 。 |
| srand( [expr] ) | 将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。 |
| srand( [expr] ) | 将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。 |
举例说明:
举例说明:
```
```sh
awk 'BEGIN{OFMT="%.3f";fs=sin(1);fe=exp(10);fl=log(10);fi=int(3.1415);print fs,fe,fl,fi;}'
awk 'BEGIN{OFMT="%.3f";fs=sin(1);fe=exp(10);fl=log(10);fi=int(3.1415);print fs,fe,fl,fi;}'
0.841 22026.466 2.303 3
0.841 22026.466 2.303 3
@ -751,7 +806,7 @@ OFMT 设置输出数据格式是保留3位小数。
获得随机数:
获得随机数:
```
```sh
awk 'BEGIN{srand();fr=int(100*rand());print fr;}'
awk 'BEGIN{srand();fr=int(100*rand());print fr;}'
78
78
awk 'BEGIN{srand();fr=int(100*rand());print fr;}'
awk 'BEGIN{srand();fr=int(100*rand());print fr;}'
@ -776,12 +831,11 @@ awk 'BEGIN{srand();fr=int(100*rand());print fr;}'
| toupper( String ) | 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
| toupper( String ) | 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
| sprintf(Format, Expr, Expr, . . . ) | 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。 |
| sprintf(Format, Expr, Expr, . . . ) | 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。 |
注: Ere都可以是正则表达式。
注: Ere都可以是正则表达式。
** gsub,sub使用**
** gsub,sub使用**
```
```sh
awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'
awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'
this is a test!test!
this is a test!test!
```
```
@ -790,7 +844,7 @@ this is a test!test!
** 查找字符串( index使用) **
** 查找字符串( index使用) **
```
```sh
awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}'
awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}'
ok
ok
```
```
@ -799,14 +853,14 @@ ok
** 正则表达式匹配查找(match使用) **
** 正则表达式匹配查找(match使用) **
```
```sh
awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}'
awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}'
ok
ok
```
```
** 截取字符串(substr使用) **
** 截取字符串(substr使用) **
```
```sh
[wangsl@centos5 ~]$ awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}'
[wangsl@centos5 ~]$ awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}'
s is a tes
s is a tes
```
```
@ -815,7 +869,7 @@ s is a tes
** 字符串分割( split使用) **
** 字符串分割( split使用) **
```
```sh
awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}'
awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}'
4
4
4 test
4 test
@ -840,8 +894,7 @@ awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA
| %e | 指数形式的浮点数 | %x | %X 无符号以十六进制表示的整数 |
| %e | 指数形式的浮点数 | %x | %X 无符号以十六进制表示的整数 |
| %o | 无符号以八进制表示的整数 | %g | 自动选择合适的表示法 |
| %o | 无符号以八进制表示的整数 | %g | 自动选择合适的表示法 |
```sh
```
awk 'BEGIN{n1=124.113;n2=-1.224;n3=1.2345; printf("%.2f,%.2u,%.2g,%X,%on",n1,n2,n3,n1,n1);}'
awk 'BEGIN{n1=124.113;n2=-1.224;n3=1.2345; printf("%.2f,%.2u,%.2g,%X,%on",n1,n2,n3,n1,n1);}'
124.11,18446744073709551615,1.2,7C,174
124.11,18446744073709551615,1.2,7C,174
```
```
@ -858,7 +911,7 @@ awk 'BEGIN{n1=124.113;n2=-1.224;n3=1.2345; printf("%.2f,%.2u,%.2g,%X,%on",n1,n2,
** 打开外部文件( close用法) **
** 打开外部文件( close用法) **
```
```sh
awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}'
awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}'
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
@ -867,14 +920,14 @@ daemon:x:2:2:daemon:/sbin:/sbin/nologin
** 逐行读取外部文件(getline使用方法) **
** 逐行读取外部文件(getline使用方法) **
```
```sh
awk 'BEGIN{while(getline < "/etc/passwd"){print $0;};close("/etc/passwd");}'
awk 'BEGIN{while(getline < "/etc/passwd"){print $0;};close("/etc/passwd");}'
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
```
```
```
```sh
awk 'BEGIN{print "Enter your name:";getline name;print name;}'
awk 'BEGIN{print "Enter your name:";getline name;print name;}'
Enter your name:
Enter your name:
chengmo
chengmo
@ -883,7 +936,7 @@ chengmo
** 调用外部应用程序(system使用方法) **
** 调用外部应用程序(system使用方法) **
```
```sh
awk 'BEGIN{b=system("ls -al");print b;}'
awk 'BEGIN{b=system("ls -al");print b;}'
total 42092
total 42092
drwxr-xr-x 14 chengmo chengmo 4096 09-30 17:47 .
drwxr-xr-x 14 chengmo chengmo 4096 09-30 17:47 .
@ -903,19 +956,19 @@ b返回值, 是执行结果。
** 建指定时间(mktime使用) **
** 建指定时间(mktime使用) **
```
```sh
awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp);}'
awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp);}'
2001年01月01日 星期一 12时12分12秒
2001年01月01日 星期一 12时12分12秒
```
```
```
```sh
awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1;}'
awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1;}'
2634468
2634468
```
```
求2个时间段中间时间差, 介绍了strftime使用方法
求2个时间段中间时间差, 介绍了strftime使用方法
```
```sh
awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}'
awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}'
308201392
308201392
```
```
@ -948,4 +1001,322 @@ awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2
| %Y | 当前月份 |
| %Y | 当前月份 |
| %% | 百分号(%) |
| %% | 百分号(%) |
<!-- Linux命令行搜索引擎: https://jaywcjlove.github.io/linux - command/ -->
### 文件间隔
```sh
#双空间文件
awk'1; {print“”}'
awk'BEGIN {ORS =“\ n \ n”}; 1'
#双空间的文件已经有空行。输出文件
#在文本行之间应该包含不超过一个空白行。
# 注意: 在Unix系统上, 只有CRLF( \ r \ n) 的DOS行是
#经常被视为非空白,因此仅'NF'将返回TRUE。
awk'NF {print $ 0“\ n”}'
#三重空间文件
awk'1; {print“\ n”}'
```
### 编号和计算:
#在每行的前面加上行号为该文件(左对齐)。
#使用选项卡(\ t) 而不是空格将保留页边距。
awk'{print FNR'\ t“$ 0}'文件*
# 在每行的前面加上行号FOR ALL FILES TOGETHER, 并带有制表符。
awk'{print NR'\ t“$ 0}'文件*
#编号文件的每一行(左边的数字,右对齐)
# 如果从DOS命令提示符处键入, 则将符号加倍。
awk'{printf( “% 5d: % s \ n”, NR, $ 0) }'
#为文件的每一行编号,但如果行不是空白,则只打印数字
#记住关于\ r的Unix处理的注意事项( 如上所述)
awk'NF {$ 0 = ++ a“: ”$ 0}; 1'
awk'{print( NF? ++ a“: ”: “”) $ 0}'
# 计数行( 模拟“wc -l”)
awk'END {print NR}'
#打印每行的字段总和
awk'{s = 0; 对于( i = 1; i < = NF; i ++) s = s + $ i; 打印s}'
#添加所有行中的所有字段并打印总和
awk'{for( i = 1; i < = NF; i ++) s = s + $ i}; END {print s}'
#在用绝对值替换每个字段后,每行打印一行
awk'{for( i = 1; i < = NF; i ++) if( $ i < 0 ) $ i = -$ i ; 打 印 } '
awk'{for( i = 1; i < = NF; i ++) $ i =( $ i < 0 ) ? - $ i : $ i ; 打 印 } '
#在所有行中打印字段总数(“字数”)
awk'{total = total + NF}; END {打印总计}'文件
# 打印包含“Beth”的总行数
awk'/ Beth / {n ++}; END {print n + 0}'文件
#打印最大的第一个字段和包含它的行
# 旨在查找字段# 1中最长的字符串
awk'$ 1> max {max = $ 1; MAXLINE = $ 0}; END {print max, maxline}'
#打印每行中的字段数,然后是行
awk'{print NF':“$ 0}'
#打印每行的最后一个字段
awk'{print $ NF}'
#打印最后一行的最后一个字段
awk'{field = $ NF}; END {打印字段}'
# 打印每行超过4个字段
awk'NF> 4'
# 打印最后一个字段值大于4的每一行
awk'$ NF> 4'
创建字符串:
# 创建一个特定长度的字符串( 例如, 生成513个空格)
awk'BEGIN {while( a ++ < 513 ) s = s“”; 打 印 s } '
#在特定字符位置插入特定长度的字符串
# 示例: 在每个输入行的# 6列之后插入49个空格。
gawk --re-interval'BEGIN {while( a ++ < 49 ) s = s“”}; { sub ( / ^ 。 { 6 } / , “ & ” s ) } ; 1 '
```sh
### 阵列创作
```sh
# 接下来的2个条目不是单行脚本, 而是技术
#非常方便,因此在这里值得一试。
#创建一个名为“月”的数组,索引数字,以便该月[1]
#是'Jan',月份[2]是'Feb',月份[3]是'Mar'等等。
拆分( “1月2月3月4月5月6月7月8月9月10月11月12月”, 月, “”)
# 创建一个名为“mdigit”的数组, 用字符串索引, 这样
# mdigit [“Jan”]是1, mdigit [“Feb”]是2等等。需要“月”数组
for( i = 1; i < = 12; i ++) mdigit [month [i]] = i
```
### 文本转换和替换:
```sh
# 在UNIX环境中: 将DOS换行符( CR / LF) 转换为Unix格式
awk'{sub( / \ r $ /,“”)}; 1'# 假设每行都以Ctrl-M结尾
# 在UNIX环境中: 将Unix换行符( LF) 转换为DOS格式
awk'{sub( / $ /,“\ r”) }; 1'
# 在DOS环境下: 将Unix换行符( LF) 转换为DOS格式
awk 1
# 在DOS环境下: 将DOS换行符( CR / LF) 转换为Unix格式
# 不能用DOS版本的awk完成, 除了gawk:
gawk -v BINMODE =“w”'1'infile> outfile
# 使用“tr”代替。
tr -d \ r < infile > outfile# GNU tr版本1.22或更高
#从每行前面删除前导空格(空格,制表符)
#左对齐所有文本
awk'{sub( / ^ [\ t] + /,“”)}; 1'
#从每行末尾删除尾随空格(空格,制表符)
awk'{sub( / [\ t] + $ /,“”)}; 1'
#删除每行的前导和尾随空白
awk'{gsub( / ^ [\ t] + | [\ t] + $ /,“”)}; 1'
awk'{$ 1 = $ 1}; 1'#也会删除字段之间的额外空间
# 在每行的开头插入5个空格( 使页面偏移)
awk'{sub( / ^ /,“”)}; 1'
# 将所有文本均匀对齐到79列宽度
awk'{printf'% 79s \ n“, $ 0}'文件*
# 将所有文字放在79个字符的宽度上
awk'{l = length( ) ; s = int( ( 79-1) / 2) ; printf“% ”( s + l) “s \ n”, $ 0}'文件*
# 在每行上用“bar”代替( 查找并替换) “foo”
awk'{sub( / foo /, “bar”) }; 1'#只替换第一个实例
gawk'{$ 0 = gensub( / foo /, “bar”, 4) }; 1'#只替换第四个实例
awk'{gsub( / foo /, “bar”) }; 1'#将所有实例替换成一行
# 将“foo”替换为“bar”, 仅用于包含“baz”
awk'/ baz / {gsub( / foo /, “bar”) }; 1'
# 将“foo”替换为“bar”除了包含“baz”的行以外
awk'! / baz / {gsub( / foo /, “bar”) }; 1'
# 将“猩红”或“红宝石”或“puce”改为“红色”
awk'{gsub( / scarlet | ruby | puce /, “red”) }; 1'
# 行的反向顺序( 模拟“tac”)
awk'{a [i ++] = $ 0} END {for( j = i-1; j> = 0;) print a [j--]}'file *
#如果一行以反斜杠结尾,则将下一行追加到它(如果失败,则失败
#有多行以反斜杠结尾......)
awk'/ \\ $ / {sub( / \\ $ /,“”); getline t; 打印$ 0 t; 下一个}; 1'文件*
#打印并排序所有用户的登录名
awk -F“: ”'{print $ 1 | “sort”}'/ etc / passwd
#按每行的相反顺序打印前两个字段
awk'{print $ 2, $ 1}'文件
#切换每行的前两个字段
awk'{temp = $ 1; $ 1 = $ 2; $ 2 = temp}'文件
#打印每一行,删除该行的第二个字段
awk'{$ 2 =“”; 打印}'
#按相反顺序打印每行的字段
awk'{for( i = NF; i> 0; i--) printf( “% s”, $ i) ; print“”}'file
# 使用逗号分隔符连接每5行输入
#字段之间
awk'ORS = NR% 5? “, ”: “\ n”'文件
```
### 选择性印刷某些线条
```sh
# 打印前10行文件( 模拟“head”的行为)
awk'NR < 11 '
# 打印文件的第一行( 模拟“head -1”)
awk'NR> 1 {exit}; 1'
# 打印文件的最后两行( 模拟“tail -2”)
awk'{y = x“\ n”$ 0; x = $ 0}; END {print y}'
# 打印文件的最后一行( 模拟“tail -1”)
awk'END {print}'
# 只打印符合正则表达式的行( 模拟“grep”)
awk'/ regex /'
# 只打印与正则表达式不匹配的行( 模拟“grep -v”)
awk'! / regex /'
# 打印字段# 5等于“abc123”的任何行
awk'$ 5 ==“abc123”'
# 仅打印字段# 5不等于“abc123”的行
# 这也将打印少于5个字段的行。
awk'$ 5! =“abc123”'
awk'! ( $ 5 ==“abc123”) '
#将字段与正则表达式匹配
awk'$ 7〜/ ^ [af] /'# print line if field# 7 matches regex
awk'$ 7! 〜/ ^ [af] /'# print line if field# 7 does not match regex
#在正则表达式之前立即打印行,但不是行
#包含正则表达式
awk'/ regex / {print x}; {x = $ 0}'
awk'/ regex / {print( NR == 1? “match line 1: x) }; {x = $ 0}'
#在正则表达式之后立即打印行,但不是行
#包含正则表达式
awk'/ regex / {getline; print}'
# grep for AAA和BBB和CCC( 在同一行上以任意顺序)
awk'/ AAA / & & / BBB / & & / CCC /'
# grep用于AAA和BBB和CCC( 按此顺序)
awk'/AAA.*BBB.*CCC/'
# 只能打印65个字符或更长的行
awk'长度> 64'
# 仅打印少于65个字符的行
awk'长度< 64 '
#从正则表达式到文件结束的文件的打印部分
awk'/ regex /, 0'
awk'/ regex /, EOF'
# 根据行号打印文件部分( 第8-12行, 含)
awk'NR == 8, NR == 12'
# 打印行号52
awk'NR == 52'
awk'NR == 52 {print; exit}'#在大文件上效率更高
#打印两个正则表达式之间的文件部分(含)
awk'/爱荷华州/, /蒙大拿州/'#区分大小写
```
### 选择性删除某些行
```sh
# 删除文件中的所有空白行( 与“grep”。'相同)
awk NF
awk'/./'
# 删除重复的连续行( 模拟“uniq”)
awk'a! 〜$ 0; {A = $ 0}”
# 删除重复的,不连续的行
awk'! a [$ 0] ++'#最简洁的脚本
awk'! ( $ a中) {a [$ 0]; print}'#最高效的脚本
# 删除重复的行
awk '!($0 in array) { array[$0]; print }' temp
```
### 统计apache日志单ip访问请求数排名( 常用, 解答方法10多种)
```sh
方法一:
awk '{++S[$1]} END {for (variable in S) print variable ,S[variable]}' access.log |sort -rn -k2
$1为第一个域的内容。-k2 为对第二个字段排序,即对数量排序。
方法二:
awk '{print $1}' access.log|sort|uniq -c |sort -rn -k1
方法三:
sed's/- -.*$//g' access.log|sort|uniq -c|sort -rn -k1
```
### 打印行号和内容:
```sh
awk '{print NR":"$0}'
输出:偶数行和奇数行到文件
awk '{print $0.txt > NR%2.txt}' file
打印出奇数行内容:(三者等价)
awk 'NR%2==1' file
awk 'NR%2' all_file.txt
awk 'i=!i' file
打印出偶数行的内容:(三者等价)
awk 'NR%2==0' file
awk '!(NR%2)' file
awk '!(i=!i)' file
```