Bash脚本let命令语法错误求助——提取法/英字幕轨道参数失败
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
-rtoreadto 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

