如何筛选第二列分组中所有行第一列均为'u'的对应行?
解决方案
可以用awk分两次遍历文件实现需求,或者利用文件已按第二列排序的特性做单遍处理,以下是两种实现方式:
方式一:双遍遍历(直观易理解)
这种方法先记录每个分组的状态,再输出符合条件的行:
NR == FNR { # 第一遍遍历:标记分组是否全为"u" if ($1 != "u") { group_valid[$2] = 0 } else if (!($2 in group_valid)) { group_valid[$2] = 1 } next } # 第二遍遍历:仅输出属于全"u"分组的行 group_valid[$2] == 1
使用时直接运行:
awk -f script.awk input.txt input.txt
逻辑说明
- 第一遍遍历文件时,对每个第二列的分组:
- 只要出现非"u"的行,就将该分组标记为无效(
0) - 若当前行是"u"且分组未被标记过,暂时标记为有效(
1)
- 只要出现非"u"的行,就将该分组标记为无效(
- 第二遍遍历文件时,只输出那些被标记为有效分组的行。
方式二:单遍遍历(利用排序特性,节省内存)
因为文件已按第二列排序,同一分组的行连续出现,可在遍历过程中实时跟踪分组状态:
BEGIN { prev_group = ""; all_u = 1; buffer = "" } { if ($2 != prev_group) { # 处理上一个分组:如果全是"u"则输出缓存内容 if (prev_group != "" && all_u) { printf "%s", buffer } # 重置当前分组的状态和缓存 prev_group = $2 all_u = ($1 == "u") ? 1 : 0 buffer = $0 "\n" } else { # 同一分组:更新状态并追加行到缓存 if ($1 != "u") { all_u = 0 } buffer = buffer $0 "\n" } } END { # 处理最后一个分组 if (all_u) { printf "%s", buffer } }
使用时运行:
awk -f script.awk input.txt
逻辑说明
- 遍历过程中维护当前分组的状态(是否全为"u")和行缓存
- 当遇到新分组时,检查上一个分组的状态:如果全是"u"则输出缓存的所有行
- 遍历结束后处理最后一个分组的内容
内容的提问来源于stack exchange,提问作者pablo
相关产品推荐
相关产品推荐

