Bash解析Fortune数据库结果与Python不符,求问题排查方案
问题
我尝试用Bash命令解析Fortune数据库文件:
$ mapfile -d '%' -t QUOTES < ~/.sigfile $ echo ${#QUOTES} 302 $
但用Python解析同一份数据库时,得到的列表长度(我认为这个结果正确)要小得多:
>>> import re >>> fort_arr = re.split(r"\n%\n", open("/home/matej/.sigfile").read()) >>> print(len(fort_arr)) 202 >>>
请问我哪里操作有误?另外我无法安装/usr/bin/fortune,所有解析必须用纯Bash及基础Unix工具完成。我注意到Stack Overflow上有近似重复的问题,但该问题已关闭且给出的方案非常繁琐复杂。
错误原因
你用Bash的mapfile时指定的分隔符是单独的%,但Fortune数据库的条目分隔符实际是换行+%+换行(\n%\n),这和Python代码里用的分隔符完全不一致。单独按%分割会把条目内容中包含的%字符也当成分隔符,导致分割出大量无效条目,所以数组长度远大于正确值。
纯Bash解决方案
方法1:用awk分割(简洁高效)
awk原生支持多行记录分隔符,能完美匹配Fortune的格式:
# 将所有条目存入数组QUOTES mapfile -t QUOTES < <(awk -v RS='\n%\n' '1' ~/.sigfile) # 输出数组长度验证结果 echo ${#QUOTES[@]}
原理:通过-v RS='\n%\n'把awk的记录分隔符设置为\n%\n,1是简化的打印指令,会输出每个分割后的条目,再用mapfile将这些条目读取到数组中。
方法2:纯Bash循环读取(无外部工具依赖)
如果不想依赖awk,可以用Bash内置的read命令结合自定义分隔符:
QUOTES=() # 以\n%\n为分隔符读取每个条目 while IFS= read -r -d $'\n%\n' quote; do QUOTES+=("$quote") done < ~/.sigfile # 处理文件末尾无分隔符的最后一个条目 [[ -n "$quote" ]] && QUOTES+=("$quote") # 输出数组长度 echo ${#QUOTES[@]}
注意:部分旧版本Bash对多行分隔符的支持可能存在兼容性问题,优先推荐awk方案。
内容的提问来源于stack exchange,提问作者mcepl
相关产品推荐
相关产品推荐

