You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本let命令语法错误求助——提取法/英字幕轨道参数失败

Fixing Subtitle Track Parameter Issue in Your Bash Script

Hey there! Let's tackle this problem you're facing with your subtitle track collection code. There are two main issues causing the error and variable loss, so let's break them down and fix them step by step:

1. The Core Problems

a) Subshell Variable Isolation

The ( while read ... done ) block runs in a subshell because it's piped from the jq command. Any variables modified inside this subshell (like subtitle_param) won't be accessible in the main shell—this is why your subtitle_param stays empty outside the loop.

b) Wrong Use of let for String Concatenation

let is designed for arithmetic operations, not string building. When you try let subtitle_param+="-map 0:$subtitle_track_number ", Bash tries to parse -map 0:6 as a math expression, which throws that syntax error.

2. The Fixes

Option 1: Avoid Subshell with Process Substitution

Rewrite the loop to run in the main shell using process substitution (< <(...)). This way, your parameter variable is modified directly in the main shell's context:

subtitle_param=""
# Use process substitution to keep the loop in the main shell
while read -r subtitle_track_number; do
    echo "Found subtitle track: $subtitle_track_number"
    # Correct string concatenation (no let needed)
    subtitle_param+="-map 0:$subtitle_track_number "
    echo "Current subtitle params: $subtitle_param"
done < <(mkvmerge --identify --identification-format json "$file.mkv" | jq -r '.tracks[] | select(.codec=="SubRip/SRT" and (.properties.language=="fre" or .properties.language=="eng")).properties.number')

Option 2: Use an Array for More Robust Parameter Handling

For better practice (especially if you might encounter spaces or edge cases later), use an array to store subtitle parameters instead of a string. This avoids messy space-related issues:

# Initialize empty array
subtitle_params=()
while read -r subtitle_track_number; do
    echo "$subtitle_track_number"
    # Add parameters to the array as separate elements
    subtitle_params+=("-map" "0:$subtitle_track_number")
    echo "Current subtitle params: ${subtitle_params[*]}"
done < <(mkvmerge --identify --identification-format json "$file.mkv" | jq -r '.tracks[] | select(.codec=="SubRip/SRT" and (.properties.language=="fre" or .properties.language=="eng")).properties.number')

# Use the array in ffmpeg with proper expansion
echo "subtitle param : ${subtitle_params[*]}"
read -p 'Continue ? : '
if [ ${#subtitle_params[@]} -eq 0 ]; then
    ffmpeg -i "$file.mkv" -map 0:v -c:v libx265 -crf "$crf" -preset medium -pix_fmt yuv420p -an "encoded/$file.mkv"
else
    ffmpeg -i "$file.mkv" -map 0:v -c:v libx265 -crf "$crf" -preset medium -pix_fmt yuv420p -map -0:a "${subtitle_params[@]}" -c:s copy "encoded/$file.mkv"
fi

Key Improvements:

  • Added -r to read to handle backslashes correctly (a safe default for most cases).
  • Removed the unnecessary subshell wrapper around the loop.
  • Array usage ensures parameters are passed correctly to ffmpeg, even if track numbers had special characters (though they won't here, it's good practice).

3. Full Modified Subtitle Handling Section

Here's how the corrected code fits into your script:

# Initialize subtitle parameters array
subtitle_params=()
# Read subtitle track numbers without subshell
while read -r subtitle_track_number; do
    echo "$subtitle_track_number"
    subtitle_params+=("-map" "0:$subtitle_track_number")
    echo "Current subtitle params: ${subtitle_params[*]}"
done < <(mkvmerge --identify --identification-format json "$file.mkv" | jq -r '.tracks[] | select(.codec=="SubRip/SRT" and (.properties.language=="fre" or .properties.language=="eng")).properties.number')

echo "subtitle param : ${subtitle_params[*]}"
read -p 'Continue ? : '
if [ ${#subtitle_params[@]} -eq 0 ]; then
    ffmpeg -i "$file.mkv" -map 0:v -c:v libx265 -crf "$crf" -preset medium -pix_fmt yuv420p -an "encoded/$file.mkv"
else
    ffmpeg -i "$file.mkv" -map 0:v -c:v libx265 -crf "$crf" -preset medium -pix_fmt yuv420p -map -0:a "${subtitle_params[@]}" -c:s copy "encoded/$file.mkv"
fi

This should fix both the syntax error and the variable not being passed to the main shell. Let me know if you need any further tweaks!

内容的提问来源于stack exchange,提问作者Victor Lebkowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 06:28:14