如何在awk或csh中按第一字段对文件内容实现分组打印输出?
问题原因
- 正则匹配逻辑错误:你原代码中
awk '/^'$name'/ {print $0} input用的是行首前缀正则匹配,当$name为A时,所有以A开头的行(AD、AC开头的行也满足)都会被匹配,导致输出多余内容。同时你打印的是整行$0,但预期输出的是第二字段$2,内容也不符合要求。 - 分组顺序错误:你用
sort | uniq获取分组列表,得到的是字典序排列的分组(A、AC、AD、B),但你预期的是按原文本中分组第一次出现的顺序(A、AD、B、AC)输出,顺序不匹配。 - 变量传递不严谨:直接把shell变量拼接到awk正则中,若分组名包含正则特殊字符会触发语法错误。
纯awk最优实现
无需多管道、多进程或者shell循环,一次遍历文件即可完成需求,效率更高,输出完全符合预期:
awk ' { # 按第一次出现的顺序保存分组名 if (!($1 in order_list)) { order_list[++total] = $1 } # 把对应分组的第二字段拼接存储 group_data[$1] = group_data[$1] $2 "\n" } END { # 按顺序输出所有分组 for (i=1;i<=total;i++) { key = order_list[i] print "#########" print "#### " key print "#########" printf "%s", group_data[key] } } ' input
原csh代码修复版本
如果要保留原有csh循环的写法,修改后也可正常运行:
# 按原文本第一次出现的顺序获取唯一分组,不需要sort|uniq set my_sort = `awk '!seen[$1]++ {print $1}' input` foreach name ($my_sort) echo "#########" echo "#### $name" echo "#########" # 用-v传变量,精确匹配第一字段,只打印第二字段 awk -v n="$name" '$1 == n {print $2}' input end
内容的提问来源于stack exchange,提问作者masifq
相关产品推荐
相关产品推荐

