【问题标题】:Bash variable does not save the dataBash 变量不保存数据
【发布时间】:2018-03-23 10:48:09
【问题描述】:

我写了这个脚本:

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,则发送返回预期结果。

如果我在fi 之后创建echo $ sent,则变量已经为空。显然,通过这种方式,两个元素被添加到帐户中,并且发送了两封邮件而不是一个。

我做错了什么?

【问题讨论】:

  • Piping (|) 创建子外壳,其变量在“父”外壳中“不可见”。
  • 从技术上讲,重复是标题中问题的直接解决方案,但这里有很多问题,所以我认为回答比重复更有意义。

标签: bash shell


【解决方案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 数组中的任何有意义的东西都应该可以忽略不计(尽管实际上将它放在数组中很可能是您的基本错误)并显着简化了脚本的其余部分。这样,您也不必跟踪下游代码中的重复项,并且避免多次循环遍历相同的值和文件。

【讨论】:

    【解决方案2】:

    这与“Bash variable scope”相同:您将通过管道输入if 语句,该语句创建一个子shell。子 shell 有一个新的作用域,在 if 语句完成后丢失。

    在许多解决方案中,您可以例如echo 每次更新senttail -n1 最后整个语句只显示最后一个版本的sent

    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
    

    【讨论】:

      猜你喜欢
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 2020-05-03
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多