MacOS下source .zshrc出现Bad Math Expression错误求助
问题描述
我希望在macOS或Linux系统中,用户执行source ~/.zshrc时展示认证令牌的过期时间。直接在zsh中运行相关代码一切正常,但在macOS下执行source ~/.zshrc时抛出错误:
└─> source ~/.zshrc
check_token:35: bad math expression: operator expected at `23:17:10'
错误指向代码行:
ISO_expiry_date="${expiry_year}/${expiry_month}/${expiry_day}${expiry_time}"
完整的check_token函数代码如下:
check_token() { command="auth" token -s if [ $? -ne 0 ]; then echo "Authetication not present, running $command" eval $command if [[ $? -ne 0 ]] && [[ $? -ne 130 ]]; then check_token fi fi token -s if [ $? -eq 0 ]; then token=`tokenlist | grep string` ISO_expiry_date="" if [[ `uname` == "Linux" ]]; then expiry_date=`echo $token | awk '{print $3}'` # 从美式日期格式转为ISO格式 expiry_date_parts=(${(s[/])expiry_date}) expiry_time=`echo $token | awk '{print $4}'` ISO_expiry_date="$expiry_date_parts[3]/$expiry_date_parts[2]/$expiry_date_parts[1] $expiry_time" elif [[ `uname` == "Darwin" ]]; then expiry_day=`echo $token | awk '{print $6}'` printf -v expiry_day "%02d" $expiry_day month=`echo $token | awk '{print $5}'` expiry_month=`date -j -f "%b" "$month" +"%m"` expiry_year=`echo $token | awk '{print $8}'` expiry_time=" `echo $token | awk '{print $7}'`" ISO_expiry_date="${expiry_year}/${expiry_month}/${expiry_day}${expiry_time}" fi if [[ $ISO_expiry_date -ne "" ]]; then echo "Ticket will expire at $ISO_expiry_date" else echo "Current ticket: $token" fi fi }
macOS下tokenlist的输出示例:
Issued Expires Principal Sep 1 13:17:14 2022 Sep 1 23:17:10 2022 string
环境版本信息:
- zsh版本:
zsh --version zsh 5.8.1 (x86_64-apple-darwin21.0)
- macOS版本:
sw_vers ProductName: macOS ProductVersion: 12.5.1 BuildVersion: 21G83
问题修复
错误原因
报错的根本原因不是ISO_expiry_date的赋值行,而是后续的判断语句if [[ $ISO_expiry_date -ne "" ]]:-ne是数值比较运算符,zsh会尝试将字符串格式的ISO_expiry_date解析为数值,遇到时间中的冒号:时无法识别,从而抛出"bad math expression"错误。
修复步骤
将数值比较运算符-ne替换为字符串比较运算符!=,修改后的判断代码:
if [[ $ISO_expiry_date != "" ]]; then echo "Ticket will expire at $ISO_expiry_date" else echo "Current ticket: $token" fi
可选优化
可以优化macOS分支的代码,减少重复调用awk的次数,一次性提取所有需要的字段:
elif [[ `uname` == "Darwin" ]]; then # 用awk一次性提取过期时间的日、月、时间、年 read expiry_day month expiry_time expiry_year <<< $(echo $token | awk '{print $6, $5, $7, $8}') printf -v expiry_day "%02d" $expiry_day expiry_month=$(date -j -f "%b" "$month" +"%m") ISO_expiry_date="${expiry_year}/${expiry_month}/${expiry_day} ${expiry_time}"
内容的提问来源于stack exchange,提问作者difurious
相关产品推荐
相关产品推荐

