如何在Bash脚本中检测多行输出字符串并获取对应index值
嘿,既然你已经有Bash脚本基础,那咱们直接来搞定这个需求——既要检测DTS流存在,又要拿到对应index,最优的思路是只调用一次ffprobe,避免重复解析视频文件浪费资源,下面给你几个靠谱的方案,按推荐程度排序:
1. 首选:用awk一次性搞定(无额外依赖)
awk天生适合处理这种分块的文本,能精准定位到包含codec_name=dts的[STREAM]块,同时提取对应的index,而且是Linux系统默认自带的工具,不用额外安装。
直接上代码:
# 提取所有DTS流的index,存进数组 dts_indices=($(/usr/sbin/ffprobe -show_streams -i "$source" 2>/dev/null | awk ' # 进入新的STREAM块时,标记状态并重置当前index /^\[STREAM\]/ { in_stream=1; current_index="" } # 退出STREAM块时,取消标记 /^\[\/STREAM\]/ { in_stream=0 } # 在STREAM块内,遇到index行就提取数值 in_stream && /^index=/ { current_index=substr($0, index($0,"=")+1) } # 在STREAM块内,遇到DTS编码时,输出之前存的index in_stream && /^codec_name=dts/ { print current_index } ')) # 判断是否找到DTS流 if [ ${#dts_indices[@]} -gt 0 ]; then echo "检测到DTS流,对应的index值:${dts_indices[*]}" # 这里放你的后处理逻辑,比如遍历每个index: for idx in "${dts_indices[@]}"; do echo "正在处理index为$idx的DTS流..." # your post-processing code here done fi
这个方案的优势:
- 效率拉满:只调用一次ffprobe,大文件或批量处理时节省大量时间
- 精准匹配:不会跨流块乱匹配(比如不会把前一个流的index和当前流的DTS绑定)
- 支持多流:如果视频有多个DTS音频流,能一次性提取所有index
2. 进阶:用JSON输出+jq解析(可读性更强)
如果你的系统装了jq(轻量级JSON处理工具,大部分发行版可以用apt install jq或yum install jq安装),可以让ffprobe输出结构化的JSON,然后用jq精准筛选,逻辑更直观,不容易出错。
代码示例:
# 提取所有DTS流的index dts_indices=($(/usr/sbin/ffprobe -show_streams -i "$source" -of json 2>/dev/null | jq -r '.streams[] | select(.codec_name == "dts") | .index')) if [ ${#dts_indices[@]} -gt 0 ]; then echo "找到DTS流,index列表:${dts_indices[*]}" # 你的后处理代码 fi
这个方案的好处是:ffprobe的JSON输出结构稳定,不用担心文本格式变化(比如不同版本ffprobe的键值对空格差异),而且jq的语法非常直观,后期维护起来很轻松。
3. 备选:grep+awk快速验证(不推荐用于生产)
如果只是临时测试,也可以用grep的上下文参数快速捞结果,但这个方法有局限性(比如index行和dts行的距离超过指定上下文就会失效,多流场景只能拿到最后一个index),适合快速验证,不推荐用于正式脚本:
# 提取最后一个DTS流的index index=$(/usr/sbin/ffprobe -show_streams -i "$source" 2>/dev/null | grep -B 10 "codec_name=dts" | grep "^index=" | tail -1 | cut -d= -f2) if [ -n "$index" ]; then echo "找到DTS流,index为$index" # 你的代码 fi
总结
- 优先用awk方案:无依赖、高效、稳定
- 有jq的话选JSON+jq:可读性和可维护性更好
- 避免用grep上下文方案:可靠性不足
内容的提问来源于stack exchange,提问作者TMC
相关产品推荐
相关产品推荐

