如何在Bash中通过for循环遍历结构化文件的分块内容
需求场景
我有一个包含如下“结构化”文本的文件:
>some multiline- >text --- >in multiple chunks (this one for instance is the second of this sample) --- >Their number, sizes and content are irregular --- >they can't >be known in >advance --- >And they'll contain pretty much any char whatsoever known or unknown in the universe >like 𒊺/🫘/ /... ---
我希望通过for循环(强烈偏好此方式)读取这些分块,写法类似:
for chunk in $(someUnknownMagic --over content.file) do echo "I'll do something with ${chunk}" done
限制条件
不能使用以下方式:
IFS:仅支持单字符分隔符列表,无法处理多行的---分隔sed转换\n---\n后配合IFS:担心转换用的分隔符可能出现在分块内容中
可行解决方案
方法1:用awk替换分隔符为特殊控制字符,配合IFS(简单高效)
我们选用ASCII里的单位分隔符(\x1F),这个字符几乎不会出现在任何普通文本里,完全可以作为安全的临时分隔符。用awk把单独一行的---替换成这个字符,再设置IFS为该字符实现分块读取:
# 设置临时分隔符为ASCII单位分隔符 IFS=$'\x1F' # 用awk处理文件,将每个分块用\x1F分隔输出 for chunk in $(awk ' BEGIN { RS="^---$"; ORS="\x1F" } # 把单独一行的---作为记录分隔符,输出用\x1F分隔 { sub(/^\n/, ""); sub(/\n$/, ""); # 去掉分块前后多余的换行 print } ' content.file) do echo "===== 开始处理分块 =====" echo "${chunk}" done # 恢复默认IFS unset IFS
方法2:用awk生成bash数组,遍历数组(极端场景兼容)
如果连控制字符都可能出现在分块里(极端情况),可以让awk直接生成bash数组的定义语句,通过eval加载后遍历数组:
# 用awk生成bash数组定义,自动转义分块里的单引号 eval "$(awk ' BEGIN { print "chunks=(" RS="^---$" # 以单独一行的---作为分块分隔符 q="'"'"'" # 定义单引号变量,方便转义 } { gsub(q, q q); # 把分块里的单引号转义成两个单引号,避免bash语法错误 print q $0 q " " # 用单引号包裹每个分块,作为数组元素 } END { print ")" } ' content.file)" # 遍历数组处理每个分块 for chunk in "${chunks[@]}" do echo "===== 开始处理分块 =====" echo "${chunk}" done
内容的提问来源于stack exchange,提问作者Ar3s
相关产品推荐
相关产品推荐

