Bash变量不保存数据

时间:2018-03-23 10:48:09

标签: bash shell

我写这个脚本:

for ip in ${ARRAY[*]}; do
  for e in ${ARRAY[*]}; do
    echo $e
  done | grep -c "$ip" | if [[ "$(cat)" -lt "10" && $sent != *"$ip"* ]]; then
      sent=$sent$ip
      sed -n "/$ip/p" $1 | mail -s "subject" "mail@mail.mail"
    fi
done

我想从ARRAY获取每个元素,并计算此项目在ARRAY中的时间。如果此计数小于10并且此元素是第一次计算(为避免计算元素两次),则会发送一封电子邮件。

但是,sent变量不保存字符串连接。如果我在赋值后立即生成echo $ sent,则发送返回预期结果。

如果我在echo $ sent后面fi,则该变量已为空。显然,通过这种方式,两个元素正在考虑并且发送两封邮件而不是一封。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

您的尝试在语法和效率方面存在许多问题。尝试使用http://shellcheck.net/进行即时修复(不正确的引用等),但你真的应该重构像

这样的东西
printf '%s\n' "${ARRAY[@]}" |
sort | uniq -c | sort -rn |
while read -r count ip; do
    case $count in [1-9]) break;; esac   # stop looping after 10
    sed -n "/$ip/p" "$1" | mail -s "subject" "mail@mail.mail"
done

对于任何有意义的存储在Bash数组中的任何事情,排序的开销应该可以忽略不计(尽管将它放在数组中可能实际上是你的基本错误)并且显着简化了脚本的其余部分。这样,您就可以避免跟踪下游代码中的重复项,并避免多次循环遍历相同的值和文件。

答案 1 :(得分:0)

这与" Bash variable scope"相同:您正在进入if语句,这会创建一个子shell。子shell有一个新的作用域,在if语句完成后会丢失。

在众多解决方案中,您可以echo每次更新senttail -n1最后的整个语句,只显示sent的最后一个版本:< / p>

for ip in "${ARRAY[@]}"; do
  for e in "${ARRAY[@]}"; do
    echo "$e"
  done | grep -c "$ip" | if [[ "$(cat)" -lt "10" && $sent != *"$ip"* ]]; then
      sent=$sent$ip
      sed -n "/$ip/p" "$1" | mail -s "subject" "mail@mail.mail"
      echo "$sent"
    fi
done | tail -n1