【问题标题】:Conditional loop issue in shellshell中的条件循环问题
【发布时间】:2018-09-09 04:14:06
【问题描述】:

我有一个带有 if 和 elif 逻辑的 shell 脚本。我正在尝试使用 grep 命令检查关键字匹配。无论我传递脚本的关键字是什么,都只执行最后一个块。这是我的脚本。

tail -n 0 -F hive-server2.log | \
while read LINE
do
if [ `echo "$LINE" | grep -c "select .*" ` -gt 0 ]
then
  AuditTypeID=15
  QueryResult=$(grep -oEi 'SELECT .*' hive-server2.log | sed -n \$p)
elif [ `echo "$LINE" | grep -c "CREATE" ` -gt 0 ]
then
  AuditTypeID=13
  QueryResult="$(grep -oEi 'CREATE EXTERNAL TABLE [a-zA-Z][a-zA-Z0-9_]*' hive-server2.log | sed -n \$p)"
fi
done

如果我通过“select * from table”,它只执行 elif 部分。即使我通过任何查询它正在执行 elif 部分。任何帮助将不胜感激。

【问题讨论】:

  • 你在哪里传递参数给这个脚本?你似乎是 tail-ing 从文件中读取行
  • @TejuPriya:附注:第一个 grep 模式中的 .* 是多余的。
  • @TejuPriya:在您发布的脚本中,即使是 elif 部分也无法执行。你正在写tail -n 0,这意味着从日志文件中取出最后的零行,即没有任何东西被输送到循环中并且第一个读取已经失败。如果你真的观察到 elif 部分执行的行为,它不可能来自这个脚本。顺便说一句,结合 -n-F 选项没有意义。
  • @TeuPriya 请在您的帖子中向我们展示输入和输出示例,这样我们可以更好地了解要求。
  • 第一个select不应该是大写吗?

标签: bash shell awk sed sh


【解决方案1】:

我的模拟适用于:

tail -n 0 -F hive-server2.log | \
while read line; do
    if [[ "$line" =~ select[[:blank:]]count ]]; then
        echo "action select count"
    elif [[ "$line" =~ select[[:blank:]]\*[[:blank:]]from ]]; then
        echo "action select * from"
    elif [[ "$line" =~ DROP ]]; then
        echo "action drop"
    elif [[ "$line" =~ CREATE ]]; then
        echo "action create"
    fi
done
  • tripleee 所说:
    • tail -n 0 -f 开始读取文件而不回溯
    • tail -n 1 -f 回溯并打印最后一行
  • 如果您使用 echo 进行测试,请确保引用,例如:
    echo "select * from table" >> hive-server2.log

【讨论】:

  • HI,当我使用 echo 进行测试时,它工作正常。但是在为下一次迭代复制输出时,它不起作用。
  • 好的,但我不明白,不管测试多少,它都有效 echo 是一种处理方式,它与循环无关?也许您可以更清楚:“但是在为下一次迭代复制输出时”
  • tail -n 0 -f 开始读取文件而不回溯。 tail -n 1 回溯并打印最后一行。
【解决方案2】:

您的逻辑看起来很像您需要发现case 语句。

tail -n 0 -F hive-server2.log |  # No backslash necessary here
tr A-Z a-z |  # Convert to lower case
while read -r line    # -r option; lowercase variable
do
    case $line in
      *'select '*)
          AuditTypeID=15
          QueryResult="$(grep -oEi 'SELECT .*' hive-server2.log | sed -n \$p)";;
       *create*)
          AuditTypeID=13
          QueryResult="$(grep -oEi 'CREATE EXTERNAL TABLE [a-zA-Z][a-zA-Z0-9_]*' hive-server2.log | sed -n \$p)";;
done

反模式if [ $(echo "blah" | grep -c something) -gt 0 ] 很常见但非常单一(参见useless use of grep);检查grep 是否匹配的方法只是if echo "blah" | grep -q something,但在这里,您显然可以使用shell 的内置模式匹配工具来进一步简化。

大写变量名保留给系统使用;我建议所有脚本的私有变量都使用小写或混合大小写。

您的代码可能还有其他错误(重新读取整个文件以找到最新的 createselect 语句看起来很像您应该重构的东西)但直接的问题似乎是您匹配的是小写字母对大写模式的字符串。上面的代码将输入折叠为小写,这是一个简单的修复,但并不总是一个理想的解决方法(也许你想在输出中看到原始行,而不是大小写折叠的版本?)。 Bash 4.x 提供了一个简单的 case-folding 工具,因此您可以说 case ${line,,} 并删除 tr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 2019-12-10
    • 2019-11-08
    相关资源
    最近更新 更多