如何用AWK将含任意空白分隔的邮件列表分割为多行记录
问题场景
有一个包含5条邮件地址记录的Bash变量mailing_list,记录之间以包含任意数量空白字符的空行分隔。尝试用AWK设置不同的记录分隔符(RS)来分割记录并统计数量,但最后一段代码返回的记录数为7,与实际的5条不符,需要实现正确的分割统计。
用户的测试脚本如下:
#!/usr/bin/bash mailing_list="Jane Doe 123 Main Street Anywhere, SE 12345-6789 John Smith 456 Tree-lined Avenue Smallville, MW 98765-4321 Amir Faquer C. de la Lusitania 98 08206 Sabadell Amir Faquer w spaces before C. de la Lusitania 98 08206 Sabadel Wife w spaces before C. de la Lusitania 98 08206 Sabadell " echo "$mailing_list"|awk -v RS='' -v FS=' ' '/.*/ END {print "The number of records is "NR"."}' echo "$mailing_list"|awk -v RS=' +' -v FS=' ' '/.*/ END {print "The number of records is "NR"."}' echo "$mailing_list"|awk -v RS=' * +' -v FS=' ' '/.*/ END {print "The number of records is "NR"."}'
解决方案
方法1:使用GNU AWK(gawk)的正则记录分隔符
GNU AWK支持正则表达式作为RS,可以直接匹配任意含空白的空行(包括连续的)作为分隔符:
echo "$mailing_list" | gawk -v RS='[[:space:]]*(\\n[[:space:]]*)+' 'NF {count++} END {print "The number of records is " count "."}'
RS='[[:space:]]*(\\n[[:space:]]*)+':匹配任意数量的空白字符,加上一个或多个「换行+任意空白字符」的组合,无论空行里有多少空格/制表符、无论有多少连续空行,都会被视为单个分隔符。NF {count++}:仅统计非空记录(NF是当前记录的字段数,非空记录至少有一个字段),避免空记录干扰计数。
方法2:兼容POSIX AWK的通用写法
如果无法使用GNU AWK,可先预处理文本,统一空行格式后再统计:
echo "$mailing_list" | awk '{ if (/^[[:space:]]*$/) { if (!blank_printed) { print "" blank_printed = 1 } } else { print blank_printed = 0 } }' | awk 'BEGIN {RS=""} {count++} END {print "The number of records is " count "."}'
- 第一段awk:将所有含空白的空行替换为单个普通空行,同时压缩连续空行,确保记录之间只有单个空行分隔。
- 第二段awk:使用
RS=""(POSIX AWK默认的多空行分隔符)分割记录并统计数量。
错误原因说明
最后一段代码RS='\n *\n+'的问题在于:
- 仅匹配「换行+空格+一个或多个换行」,无法覆盖开头/结尾的空白空行,也无法处理空行前后有制表符的情况。
- 遇到连续的「换行+空格+换行+空格+换行」时,会被拆分成多个分隔符,导致中间产生额外的空记录或误将记录内部的行尾空格+换行识别成分隔符,最终统计出多余的记录数。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

