官方文档:https://www.gnu.org/software/gawk/manual/gawk.html
什么是awk?
Awk是一种文本处理工具,它的名字是由其三位创始人(Aho、Weinberger和Kernighan)的姓氏首字母组成的。Awk的设计初衷是用于处理结构化文本数据,它提供了强大的模式匹配和数据提取功能。
Awk的工作方式是逐行扫描输入文本文件,并对每一行应用一组用户定义的规则。这些规则由模式-动作对构成,当文本行匹配某个模式时,对应的动作将被执行。Awk将输入文本自动分割成字段(默认以空格作为分隔符),可以方便地对字段进行操作和处理。
语法格式
awk 'pattern { action }' input_file
- `pattern`是用于匹配文本行的条件。可以是正则表达式、比较表达式、逻辑表达式等。如果省略pattern,则默认匹配所有行。
- `{ action }`是在匹配成功时执行的动作块。可以是一条或多条语句,用花括号 {} 包围。如果省略动作块,将默认执行打印整行的操作。
- `input_file`是要处理的输入文件。如果省略此参数,则从标准输入读取数据。
常见要点
字段和字段分隔符:
- 默认情况下,Awk将每一行分割成多个字段,字段之间以空格或制表符作为分隔符。
- 可以使用`-F`选项指定不同的字段分隔符。例如,`-F ','`表示使用逗号作为分隔符。
- 可以使用`$1`、`$2`等表示第1、第2个字段,`$0`表示整行。
内置变量:
- `NR`表示当前处理的行数。
- `NF`表示当前行的字段数量。
- `FNR`表示当前文件中的行数。
- `FILENAME`表示当前处理的文件名。
控制流语句:
- `if-else`条件语句:根据条件执行不同的动作。
- `for`循环语句:迭代执行一系列动作。
- `while`循环语句:在满足条件的情况下重复执行一系列动作。
- `do-while`循环语句:先执行一系列动作,然后根据条件重复执行。
内置函数:
Awk提供了许多内置函数,可用于字符串处理、数学运算、日期处理等。例如:`length()`、`substr()`、`tolower()`、`toupper()`、`sin()`、`cos()`等。
输出打印:
- 使用`print`语句将结果输出到标准输出。可以打印文本、变量、表达式等。
- 使用`printf`函数以格式化的方式打印输出。
示例
-- 使用Awk来统计文件中的行数:
awk '{ count++ } END { print count }' input.txt
-- 使用Awk计算一个CSV文件中某一列的总和:
awk -F ',' '{ sum += $3 } END { print sum }' data
-- 使用Awk从日志文件中提取特定时间段内的日志记录:
awk '/Jun 15 10:30:00/, /Jun 15 11:00:00/' access.log
-- 使用Awk计算一个文本文件中每个单词的出现次数:
awk '{ for(i=1; i<=NF; i++) count[$i]++ } END { for(word in count) print word, count[word] }' text.txt
-- 使用正则表达式匹配包含数字的行:
awk '/[0-9]+/' input.txt
-- 计算每行字段数量,并打印行号和字段数量:
awk -F ',' '{ print "Line", NR, "has", NF, "fields" }' data.csv
-- 打印文件名和行号:
awk '{ print "File:", FILENAME, "Line:", NR, $0 }' file1.txt file2.txt
-- 使用`if-else`条件语句来根据条件执行不同的动作:
awk '{ if ($1 > 10) print $1, "is greater than 10"; else print $1, "is less than or equal to 10" }' data.txt
-- 使用`for`循环语句打印九九乘法表:
awk 'BEGIN { for(i=1; i<=9; i++) { for(j=1; j<=i; j++) printf("%d*%d=%d ", j, i, i*j); print "" } }'
-- 使用`length()`函数获取每行的字符数:
awk '{ print "Line", NR, "has", length($0), "characters" }' data.txt
-- 使用`substr()`函数截取字段的子字符串:
awk -F ',' '{ print "Name:", $1, "Initials:", substr($1, 1, 1) substr($2, 1, 1) }' names.csv
-- 使用`print`语句打印文本和变量:
awk '{ name = $1; age = $2; print "Name:", name, "Age:", age }' data.txt
-- 使用`printf`函数以格式化的方式打印输出:
awk '{ printf "Name: %-10s Age: %2d\n", $1, $2 }' data.txt
-- 删除temp文件的重复行
awk '!($0 in array) { array[$0]; print }' temp
-- 查看最长使用的10个命令
awk '{print $1}' ~/.bash_history | sort | uniq -c | sort -rn | head -n 10
-- 查看机器的ip列表
ifconfig -a | awk '/Bcast/{print $2}' | cut -c 5-19
-- 查看机器的每个远程链接机器的连接数
netstat -antu | awk '$5 ~ /[0-9]:/{split($5, a, ":"); ips[a[1]]++} END {for (ip in ips) print ips[ip], ip | "sort -k1 -nr"}'
-- 查看某个进程打开的socket数量
ps aux | grep [process] | awk '{print $2}' | xargs -I % ls /proc/%/fd | wc -l
-- 批量重命名文件
find . -name '*.jpg' | awk 'BEGIN{ a=0 }{ printf "mv %s name%01d.jpg\n", $0, a++ }' | bash
-- 查看某个用户打开的文件句柄列表
for x in `ps -u 500 u | grep java | awk '{ print $2 }'`;do ls /proc/$x/fd|wc -l;done
-- 计算文件temp的第一列的值的和
awk '{s+=$1}END{print s}' temp
-- 查找某个时间戳的文件列表
cp -p `ls -l | awk '/Apr 14/ {print $NF}'` /usr/users/backup_dir
-- 格式化输出当前的进程信息
ps -ef | awk -v OFS="\n" '{ for (i=8;i<=NF;i++) line = (line ? line FS : "") $i; print NR ":", $1, $2, $7, line, ""; line = "" }'
-- 查看输入数据的特定位置的单个字符
echo "abcdefg"|awk 'BEGIN {FS="''"} {print $2}'
-- 打印当前的ssh客户端
netstat -tn | awk '($4 ~ /:22\s*/) && ($6 ~ /^EST/) {print substr($5, 0, index($5,":"))}'
-- 打印文件第一列不同值的行
awk '!array[$1]++' file.txt
-- 打印第二列唯一值
awk '{ a[$2]++ } END { for (b in a) { print b } }' file
-- 查看系统所有分区
awk '{if ($NF ~ "^[a-zA-Z].*[0-9]$" && $NF !~ "c[0-9]+d[0-9]+$" && $NF !~ "^loop.*") print "/dev/"$NF}' /proc/partitions
-- 查看2到100所有质数
for num in `seq 2 100`;do if [ `factor $num|awk '{print $2}'` == $num ];then echo -n "$num ";fi done;echo
-- 查看第3到第6行
awk 'NR >= 3 && NR <= 6' /path/to/file
分享、在看与点赞
只要你点,我们就是胖友
来自: Linux文本处理三剑客之awk命令https://mp.weixin.qq.com/s?__biz=Mzk0NTQ3OTk3MQ==&mid=2247487424&idx=1&sn=53c4b2333d8e6e42831ad1e362040251&chksm=c315878cf4620e9abca074f1c66d97750c0587b487c51df45d41e664ceb7435ebbfe3869fae9&token=355315523&lang=zh_CN#rd