我有一个脚本执行SQL SELECT并使用输出发送一些电子邮件,但脚本出现问题导致错误消息:
第34行:johne@mail.com:语法错误:算术运算符无效 (错误令牌是“@ mail.com”)
第34行是:
if (( ${msgData[$email]:-0} < $(LC_TIME=C date -d yesterday +%s) )); then
这是脚本:
#!/bin/bash
${BASH_VERSION+shopt -s extglob lastpipe} 2>/dev/null
# Full path to a file to store our date offset data. Will be overwritten.
datefile=date.log
# Assign your vars or insert whatever code does so here.
user=user pass=pass db=db
function doit {
typeset x
for x; do
if [[ -z $x ]]; then
echo 'doit: missing an argument.' >&2
return 1
fi
done
typeset template=$(</dev/fd/4)
exec 4<&-
sqlplus "${1}/${2}@${3}" <&3 | {
if [[ -f $datefile ]]; then
. "$datefile" || return 1
else
# An associative array that maps from num -> timestamp
typeset -A msgData
fi
# If we've successfully read the file containing timestamps, then overwrite with new data on RETURN
${msgData+trap 'trap RETURN; typeset -p msgData >"$datefile"' RETURN}
while IFS=, read -r num email limit orders; do
${email:+:} continue
if (( ${msgData[$email]:-0} < $(LC_TIME=C date -d yesterday +%s) )); then
printf -- "$template" "email" "$num" "$limit" "$orders" |
/usr/sbin/sendmail -f sender@example.com -oi -t
msgData[$email]=$(LC_TIME=C date +%s)
else
printf 'Mail already sent to %s within the last 24 hours... skipping.\n' "$email" >&2
fi
done
}
} 5<&0 <<\SQL 3<&0 <<\TEMPLATE 4<&0 <&5-
set pagesize 0
set feedback 0
SELECT kred_lim.kunr ||','|| kust_adr.ku_email ||','|| kred_lim.kred_limit ||','|| kred_lim.kred_zu_zahlen
FROM kred_lim, kust_adr
WHERE kred_lim.kred_zu_zahlen > kred_lim.kred_limit
AND kred_lim.kunr = kust_adr.ku_nr;
SQL
Subject: Credit limit
To: %s
Customer number: %s
Credit limit: %s
Current orders: %s
TEMPLATE
if ! doit "$user" "$pass" "$db"; then
echo 'we failed :(' >&2
exit 1
fi
答案 0 :(得分:3)
问题是您正在尝试在算术表达式中执行字符串比较。切换到复合表达式:
if [[ ${msgData[$email]:-0} < $(LC_TIME=C date -d yesterday +%s) ]]; then
或检查您是否正在访问msgData
的正确元素。
答案 1 :(得分:2)
在我看来,这是bash中关联数组实现的限制(截至此处的v4.3.11)。
使用
创建关联数组declare -A name.
将数组分配给使用格式
的复合赋值name=(value1 value2 … )
其中每个值的格式为
[subscript]=
string 。
然后你提前几行查看subscript
:
下标被视为必须计算为数字的算术表达式。
所以它说了一个字符串&#34; foo @ bar&#34;无法评估数字,不能用作数组键?但这并不能解释为什么没有&#34; @&#34;可以。
令人困惑的部分也是当您手动进行分配时,例如
declare -A emails_to_accounts=( \
["foo@bar.com"]="baz" \
["qux@bar.com"]="quux" \
)
for email in "${!emails_to_accounts[@]}"; do
name=${emails_to_accounts[${email}]}
: [...whatever...]
done
工作正常。烦。
事实证明,解决方法是重复分配中的declare -A
部分,如下所示:
declare -A "hash_name+=([$email]=$whatever)"
在上面的具体示例中,由于您使用${msgData[$email]:-0}
比较,因此<
可能会在整数上下文中进行评估。
所以我打赌你想做一些事情,比如引用它来逃避这个背景。
或者只使用较少的短号,而不使用:-
修饰符,这与行上所有其他标点符号结合时真正有助于产生线条噪音的印象。例如:
msgTime=${msgData[$email]}
test -n "$msgTime" || msgTime=0
if [ $msgTime -lt $(LC_TIME=C date -d yesterday +%s) ]; then