如何在bash脚本中读取结构化文件内带续行符的文件名列表
实现方案
方案1:awk 实现(推荐,高效简洁)
awk天然适合处理这类带行状态的文本匹配,不需要额外管道操作,处理大文件性能更好:
awk '/^File: / { in_block=1; sub(/^File: /, ""); print $0 } in_block == 1 && /^\+ / { sub(/^\+ /, ""); print $0 } in_block == 1 && !/^File: / && !/^\+ / { in_block=0 }' "$logfl"
逻辑说明:
- 匹配到
File:开头的行时,标记进入文件块,去掉前缀后输出路径 - 处于文件块状态下,匹配到
+开头的续行,去掉前缀后输出路径 - 处于文件块状态下,遇到非
File:、非+开头的行,标记退出文件块
如果需要把结果放到bash数组里遍历,可以这么写:
readarray -t file_list < <(awk ' /^File: / { in_block=1; sub(/^File: /, ""); print $0 } in_block == 1 && /^\+ / { sub(/^\+ /, ""); print $0 } in_block == 1 && !/^File: / && !/^\+ / { in_block=0 }' "$logfl") # 遍历示例 for f in "${file_list[@]}"; do echo "处理文件: $f" done
方案2:纯bash实现(无外部依赖)
如果不想依赖awk,用原生bash循环也可以实现:
in_file_block=0 while IFS= read -r line; do if [[ $line == "File: "* ]]; then in_file_block=1 # 去掉前缀提取路径 echo "${line#File: }" elif [[ $in_file_block -eq 1 && $line == "+ "* ]]; then # 去掉续行符前缀提取路径 echo "${line#+ }" elif [[ $in_file_block -eq 1 ]]; then # 遇到非续行,退出文件块 in_file_block=0 fi done < "$logfl"
内容的提问来源于stack exchange,提问作者Dilna
相关产品推荐
相关产品推荐

