Shell脚本自定义函数传参报错:日期解析变量替换问题排查
${$1:0:2}: bad substitution Error in Your Shell Script Function Hey there! Let's break down what's causing that substitution error and get your date-to-weekday function working smoothly.
The Root Cause of the Error
That bad substitution message is happening because you’re trying to nest variable references incorrectly in your function. When you write ${$1:0:2}, the shell gets confused—$1 already refers to the first argument passed to your function, and you don’t need an extra $ inside the curly braces. The correct syntax for substring extraction is ${1:0:2} (no extra dollar sign).
How to Fix Your Date Parsing Function
Let’s start with a corrected version of your function. Assuming your goal is to take a date in MM/DD/YYYY format and return the corresponding weekday, here’s a robust approach using the date command (works in Bash, Zsh, and most POSIX-compliant shells):
#!/bin/bash # Function to convert MM/DD/YYYY date to weekday name get_weekday() { # Extract month, day, year from the input date (format: MM/DD/YYYY) local date_str="$1" local month="${date_str:0:2}" local day="${date_str:3:2}" local year="${date_str:6:4}" # Convert to YYYY-MM-DD format (required for date command's -d flag) local formatted_date="${year}-${month}-${day}" # Use date command to get the full weekday name date -d "$formatted_date" +"%A" } # Check if exactly two date arguments are provided if [ $# -ne 2 ]; then echo "Usage: $0 MM/DD/YYYY MM/DD/YYYY" exit 1 fi # Get weekdays for both input dates weekday1=$(get_weekday "$1") weekday2=$(get_weekday "$2") # Output the results echo "Date $1 is a $weekday1" echo "Date $2 is a $weekday2"
Key Fixes Explained
- Removed the extra
$in substring extraction: Changed${$1:0:2}to${date_str:0:2}(or directly${1:0:2}if you skip thedate_strvariable). Using a local variable likedate_strjust makes the code more readable. - Added input validation: The script now checks if exactly two arguments are passed, which helps avoid unexpected errors from missing or extra inputs.
- Used
date -dfor reliable date parsing: Instead of manually calculating weekdays (which gets messy with leap years and calendar edge cases), leveraging thedatecommand is far more accurate and less error-prone.
Testing the Script
If you run:
./datematch.sh 01/03/1984 06/12/2008
You should get output like:
Date 01/03/1984 is a Tuesday Date 06/12/2008 is a Thursday
Notes for Portability
If you’re using a system where date -d isn’t available (like macOS), you can use gdate (from the GNU coreutils package) instead, or adjust the date line to work with macOS’s native date command:
# For macOS, replace the date line with: date -j -f "%m/%d/%Y" "$date_str" +"%A"
内容的提问来源于stack exchange,提问作者Aidan Low

