如何正确读取行格式不固定的含题目选项的文本文件
解决方案
核心思路是先对原始文件做格式归一化预处理,解决选项跨行、多选项同行的问题,再按规整后的格式读取题目和选项。
步骤1:编写预处理脚本完成格式规整
使用awk完成格式统一,输出标准格式为「每题占1行、每个选项单独占1行」:
awk '{ # 去除每行首尾空白 gsub(/^[[:space:]]+|[[:space:]]+$/, "") if (length($0) == 0) next # 判断是否为新的题目/选项行 if ($0 ~ /^[0-9]+\.-/ || $0 ~ /^[a-d]\)/) { if (prev != "") print prev # 拆分同行的多个选项,用换行分隔 gsub(/[[:space:]]+([a-d]\))/, "\n\\1") prev = $0 } else { # 把续行内容拼接到上一行末尾 prev = prev " " $0 } } END { print prev }' 原始题目文件 > 规整后题目文件
你的示例文件处理后会生成如下标准格式内容:
1.- question number 1 a) option number a1 b) option number b1 c) option number c1 d) option number d1 2.- question number 2 a) option number a2 b) option number b2 c) option number c2 d) option number d2
步骤2:调整读取逻辑
可以把预处理逻辑直接整合到读取脚本中,不需要生成中间文件:
#!/bin/bash # 边预处理边读取,无需生成中间文件 awk '{ gsub(/^[[:space:]]+|[[:space:]]+$/, "") if (length($0) == 0) next if ($0 ~ /^[0-9]+\.-/ || $0 ~ /^[a-d]\)/) { if (prev != "") print prev gsub(/[[:space:]]+([a-d]\))/, "\n\\1") prev = $0 } else { prev = prev " " $0 } } END {print prev}' 原始题目文件 | while read -r line; do if [[ $line =~ ^[0-9]+\.- ]]; then # 读取到新题目时先输出上一题的内容 if [[ -n $q ]]; then echo "题目:$q" echo "选项a:$a" echo "选项b:$b" echo "选项c:$c" echo "选项d:$d" echo "---" fi # 重置当前题的变量 q="$line" a="" b="" c="" d="" elif [[ $line =~ ^a\) ]]; then a="$line" elif [[ $line =~ ^b\) ]]; then b="$line" elif [[ $line =~ ^c\) ]]; then c="$line" elif [[ $line =~ ^d\) ]]; then d="$line" fi done # 输出最后一道题的内容 echo "题目:$q" echo "选项a:$a" echo "选项b:$b" echo "选项c:$c" echo "选项d:$d"
适配能力说明
- 自动拼接跨行的选项内容,不会出现内容截断
- 自动拆分同行的多个选项,每个选项单独识别
- 支持任意数量的题目,不需要提前硬编码题号做循环
内容的提问来源于stack exchange,提问作者Diego660
相关产品推荐
相关产品推荐

