使用awk合并文件--生成report

本文详细介绍了如何使用Shell命令对学生成绩数据进行排序、连接和处理,最终输出学生姓名与成绩的报告。包括使用join命令、排序、awk等技巧,以及不使用join的替代方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设有两个文件是这样的:

root@ubuntu:/home/zoer# cat id_name
1 naughty
2 cc
4 yy
3 zoer

root@ubuntu:/home/zoer# cat id_score
1 11
2 22
3 33
4 44

现在要求使用shell命令,做一份报告,报告格式:学生姓名+学生成绩。中间以空格分隔。

------------------------------------------------------------------------

root@ubuntu:/home/zoer# sort id_name >a
root@ubuntu:/home/zoer# sort id_score >b
root@ubuntu:/home/zoer# cat a
1 naughty
2 cc
3 zoer
4 yy
root@ubuntu:/home/zoer# cat b
1 11
2 22
3 33
4 44
root@ubuntu:/home/zoer# join a b>c
root@ubuntu:/home/zoer# cat c
1 naughty 11
2 cc 22
3 zoer 33
4 yy 44
root@ubuntu:/home/zoer# awk '{print $2," ",$3}' c
naughty   11
cc   22
zoer   33
yy   44

------------------------------------------------------------------------

上面列出了实现过程。首先对两个文件按照学号排序。排好序之后使用join命令将两个文件连接起来,然后使用awk输出后两列即可。

---------------------------------------------------------------------

上面是使用了join命令来帮忙。如果不使用join呢?看下面

root@ubuntu:/home/zoer# cat id_name id_score |sort -k 1 |awk 'BEGIN{t=""}{t=$1;if(tt==t){printf(" %s",$2);printf("\n")}else{printf("%s %s",$1,$2);}tt=t}'|awk '{print $2," ",$3}'
11   naughty
22   cc
33   zoer
44   yy

先排序,排序之后,相同id的学生信息都放在一起了。然后使用了两个awk来合并结果。【如果这里第一个awk的使用方法不明白,文章末尾还有一个例子来说明这个用法】

--》》》》》

上面的代码修改一下print,就可以只用一个awk命令了 。

root@ubuntu:/home/zoer# cat id_name id_score |sort -k 1 |awk 'BEGIN{t=""}{t=$1;if(tt==t){printf(" %s",$2);printf("\n")}else{printf("%s",$2);}tt=t}'
11 naughty
22 cc
33 zoer
44 yy

--------------------------------------------------------

再看一个awk的例子。去掉d文件中多余的第一个字段。

root@ubuntu:/home/zoer# cat d
m naughty
m cc
n zoer
n yy
n zz
root@ubuntu:/home/zoer# awk 'BEGIN{t=""}{t=$1;if(tt!=t)print $1,"\t",$2;else{print "\t",$2;}tt=t;}' d
m   naughty
      cc
n   zoer
     yy
     zz

上面的代码去掉了d文件中不必要的第一个字段。使用了记录第一个字段并且每次处理一行的时候比较第一个字段的技巧。

### 3.1 awk 的基本结构与工作原理 `awk` 是一种基于模式匹配的语言,它逐行读取输入文件或标准输入,并将每一行拆分为字段。默认情况下,字段由空格或制表符分隔。其基本语法结构如下: ```bash awk 'pattern { action }' filename ``` 其中,`pattern` 是用于匹配输入的条件,而 `{ action }` 是在匹配成功时执行的操作。如果省略 `pattern`,则对所有行执行操作;若省略 `{ action }`,则默认输出匹配的行。 `awk` 程序通常包含多个语句,它们被包裹在单引号中的花括号内。例如: ```bash awk '{ print $1, $3 }' data.txt ``` 此命令打印每行的第一个和第三个字段[^1]。 ### 3.2 字段与记录的访问 `awk` 将每一行视为一个“记录”,并将记录拆分为多个“字段”。内置变量 `$0` 表示整条记录(即当前行),`$1`, `$2`, ..., `$n` 分别表示第 1、2、...、n 个字段。字段的数量可以通过 `NF` 获取,记录的数量通过 `NR` 获取。 例如,以下命令打印每行的字段数量以及该行内容: ```bash awk '{ print "Number of fields:", NF, " - Line:", $0 }' data.txt ``` 此外,`FS` 变量用于设置字段分隔符,默认为空格和制表符。可以使用 `-F` 选项更改默认分隔符,例如以冒号作为分隔符处理 `/etc/passwd` 文件: ```bash awk -F: '{ print $1, $5 }' /etc/passwd ``` 此命令打印用户名和用户描述信息[^2]。 ### 3.3 条件判断与模式匹配 `awk` 支持多种模式匹配方式,包括正则表达式、比较运算符等。例如,仅处理包含特定字符串的行: ```bash awk '/error/ { print }' logfile.txt ``` 上述命令会打印所有包含 "error" 字符串的行。也可以使用关系运算符进行比较,如: ```bash awk '$3 > 100 { print $0 }' sales.txt ``` 此命令打印第三列大于 100 的所有行。 还可以组合多个条件,使用逻辑运算符 `&&` 和 `||`。例如: ```bash awk '$2 == "Linux" && $3 < 50 { print }' data.csv ``` 此命令打印第二列等于 "Linux" 并且第三列小于 50 的行[^3]。 ### 3.4 内置函数与自定义函数 `awk` 提供了丰富的内置函数,支持字符串处理、数学计算等功能。例如,`length()` 函数返回字符串长度,`substr()` 提取子字符串,`index()` 查找子字符串位置。 ```bash awk '{ print length($0), substr($0, 1, 5) }' file.txt ``` 此命令打印每行的长度及其前五个字符。 用户还可以定义自己的函数,例如: ```bash awk ' function square(x) { return x * x } $1 ~ /^[0-9]+$/ { print square($1) } ' numbers.txt ``` 此脚本定义了一个 `square` 函数,并对第一列为数字的行计算其平方并输出。 ### 3.5 格式化输出与报表生成 `awk` 支持使用 `printf` 进行格式化输出,类似于 C 语言中的 `printf` 函数。例如: ```bash awk '{ printf "%-10s %6.2f\n", $1, $2 }' report.txt ``` 此命令将第一列左对齐、宽度为10,第二列右对齐、保留两位小数输出。 结合 `BEGIN` 和 `END` 块,可以实现报表头和报表尾的打印: ```bash awk ' BEGIN { printf "Name Score\n" printf "------------------\n" } { total += $2 printf "%-10s %6.2f\n", $1, $2 } END { printf "Total: %6.2f\n", total } ' scores.txt ``` 此脚本打印学生姓名和成绩,并在最后输出总分[^1]。 ### 3.6 高级应用:关联数组与多文件处理 `awk` 支持使用关联数组进行高效的数据聚合。例如,统计某个字段出现的次数: ```bash awk '{ count[$1]++ } END { for (key in count) print key, count[key] }' access.log ``` 此命令统计日志文件中每个 IP 地址的访问次数。 `awk` 还可以同时处理多个文件。例如,合并两个文件并进行比对: ```bash awk 'NR == FNR { a[$1] = $2; next } $1 in a { print $1, $2, a[$1] }' file1.txt file2.txt ``` 此命令将 `file1.txt` 中的第一列作为键,第二列作为值存储到数组 `a` 中,然后在处理 `file2.txt` 时查找相同的键并输出对应的值[^2]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值