Shell脚本读取文件提取指定字段输出异常求助
解决文本块提取变量并输出的问题
你的问题核心在于原脚本的行读取逻辑和输出时机错误,导致变量收集不完整且输出混乱。我们可以通过调整逻辑,等一个完整的信息块收集完所有变量后再输出,同时修正行读取的问题。
原脚本的核心问题
- 同时使用两个
read命令,导致行读取错位,每次循环会跳过一行内容 - 每读取一行就输出一次,而不是等一个完整的信息块(从
>QDN到OPTIONS下一行)的所有变量都收集完成后再输出 - OPTIONS下一行的获取逻辑错误,没有正确定位到OPTIONS的下一行
方案1:修正Bash脚本
我们调整逻辑,遍历每一行,遇到新的>QDN块时先输出上一个块的结果(如果存在),然后重置变量;分别匹配各行收集对应变量,遇到OPTIONS行时读取下一行作为options,最后在脚本结束时输出最后一个块的结果:
#!/bin/bash # 初始化变量 number="" type="" snpa="" options="" while IFS= read -r line || [[ -n "$line" ]]; do # 遇到新的QDN块,先输出上一个块的内容(如果变量都已收集) if [[ "$line" =~ ^'>QDN' ]]; then # 如果之前的变量都不为空,输出 if [[ -n "$number" && -n "$type" && -n "$snpa" && -n "$options" ]]; then echo "$number;$type;$snpa;$options" fi # 重置变量 number="" type="" snpa="" options="" # 提取number number=$(echo "$line" | awk -F ';' '{print $2}') elif [[ "$line" =~ ^'TYPE:' ]]; then # 提取type的第2、3、4列,用空格分隔 type=$(echo "$line" | awk -F ';' '{print $2" "$3" "$4}') elif [[ "$line" =~ ^'SNPA:' ]]; then snpa=$(echo "$line" | awk -F ';' '{print $2}') elif [[ "$line" =~ ^'OPTIONS:' ]]; then # 读取下一行作为options IFS= read -r options # 去掉可能的末尾空格 options=$(echo "$options" | sed 's/[[:space:]]*$//') fi done < "file.txt" # 输出最后一个块的内容 if [[ -n "$number" && -n "$type" && -n "$snpa" && -n "$options" ]]; then echo "$number;$type;$snpa;$options" fi
方案2:使用Awk脚本(更高效简洁)
Awk天生适合处理这种结构化的文本块,我们可以把分隔线-------------------------------------------------------------------------------作为记录分隔符,然后在每个记录里提取需要的内容:
BEGIN { RS="-------------------------------------------------------------------------------" FS="\n" OFS=";" } { # 遍历当前记录的每一行 for (i=1; i<=NF; i++) { line = $i if (line ~ /^>QDN/) { split(line, arr, ";") number = arr[2] } else if (line ~ /^TYPE:/) { split(line, arr, ";") type = arr[2]" "arr[3]" "arr[4] } else if (line ~ /^SNPA:/) { split(line, arr, ";") snpa = arr[2] } else if (line ~ /^OPTIONS:/) { # 下一行就是options内容 options = $(i+1) # 去掉末尾空格 gsub(/[[:space:]]*$/, "", options) } } # 只输出变量都存在的记录 if (number != "" && type != "" && snpa != "" && options != "") { print number, type, snpa, options } }
运行方式:
awk -f extract.awk file.txt > output.txt
预期输出
对于你提供的示例输入,运行后会得到:
6135785008;SINGLE PARTY LINE;613;CWT;DGT;DDN;NOAMA; 6160160260;SINGLE PARTY LINE;616;CWT;3WC;DGT;DDN;NOAMA;
内容的提问来源于stack exchange,提问作者hadesungod




