mysql - 新手 : unix bash, 嵌套 if 语句,循环结果来自 sql

标签 mysql bash if-statement stdout tty

这里是新手,请原谅我使用的任何令人困惑的措辞。 我的一个常见任务是获取姓名列表并执行 MySQL 查询以在表中查找姓名并查看它们是否在我们的网站上“存在”。

一次执行此操作,我的 SQL 查询工作正常。然后我想使用列出多个名称的文件中的循环来执行查询。这也很好用。

我将此查询循环添加到我的 bash 配置文件中,以便我可以通过键入以下内容快速完成任务:

$ ValidOnSite fileName

这工作得很好,我什至为我的过程添加了一个使用语句来提醒自己语法。以下是我的工作正常的内容:

validOnSite() {


        if [[ "$1" == "" ]] || [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
                echo "Usage:"
                echo " $ validOnSite [filename]"
                echo " Where validOnSite uses specified file as variables in sql query:"
                echo " SELECT name, active FROM dbDb WHERE name=lines in file"
        else

                cat $1 | while read line ; do hgsql -h genome-centdb hgcentral -Ne "select name, active from dbDb where name='$line'" ; done

                fi

使用文件“list.txt”,其中包含:

nameA
nameB

然后我会输入:

validOnSite list.txt

并且list.txt中的两个条目都满足我的查询条件并且在sql中找到。我的结果将是:

nameA 1
nameB 1

注意每个结果后面的“1”。我认为这是某种"is"状态。

现在,我向 list.txt 添加了第三个名称,我知道该名称与 sql 不匹配。现在list.txt包含:

nameA
nameB
foo

当我再次对 3 行列表运行此命令时:

validOnSite 列表.txt

我的结果与我使用第一个版本的 file.txt 时相同,并且我看不到哪些行失败,我仍然只看到哪些行成功:

nameA 1
nameB 1

我一直在尝试各种方法来添加嵌套的 if 语句,即“如果 $line 匹配,则回显“通过”,否则回显“失败”。

我不想在结果中看到“1”。使用具有 2 个匹配项和 1 个不匹配项的 file.txt,我希望我的结果是:

nameA pass
nameB pass
foo fail

或者更好的是,用绿色标记通过,用红色标记失败。

正如我所说,这里是新手......:)

任何指向正确方向的指针都会有所帮助。这是我最近的悲伤尝试,但我意识到我可能完全走错了方向:

validOnSite() {


        if [[ "$1" == "" ]] || [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
                echo "Usage:"
                echo " $ validOnSite [filename]"
                echo " Where validOnSite uses specified file as variables in sql query:"
                echo " SELECT name, active FROM dbDb WHERE name=lines in file"
        else

                cat $1 | while read line ; do hgsql -h genome-centdb hgcentral -Ne "select name, active from dbDb where name='$line'" > /dev/null ; done
 if ( "status") then
      echo $line "failed"
      echo $line "failed" >> outfile
else
     echo $line "ok"
     echo $line "ok" >>outfile
     clear
     cat outfile
     fi
fi

如果在我上次尝试中某些事情看起来很疯狂,那是因为它确实如此 - 我只是在谷歌上搜索并尝试尽可能多的东西,同时尝试学习。感谢任何帮助,在工作了很长一段时间后,我感到陷入困境,但我很高兴继续前进并找到解决方案!我认为我在理解标准输出方面缺少一些东西,并且对嵌套 if 也感到困惑。

注意:我不需要输出文件,但如果需要一个输出文件来实现目标也没关系。仅 stdout 结果就足够了,并且是首选。

注意:hgssql 只是我们的 MySQL 服务器的名称。 MySQL 部分工作正常,我正在寻找一种更好的方法来处理我的 bash 输出,并且我认为我缺少一些关于 stderr 的东西。因为我是新手,所以我正在寻找一个相当简单的答案!

最佳答案

我猜,hgsql 你指的是一些允许执行 MySQL 查询的 Mercurial 扩展。我不知道 hgsql 是如何工作的,但我知道 MySQL 仅返回匹配的行。但就 shell 脚本而言,即使匹配的行数为零,结果也是可能包含额外信息的字符串。例如,某些 MySQL 客户端可能会返回 header 或类似“未找到行”的字符串,尽管这种情况不太可能发生。

我将展示如何使用官方 mysql 客户端来完成此操作。我相信您将在文档的帮助下设法将 hgsql 调整为以下示例。

if [ -t 1 ]; then
  red_color=$(tput setaf 1)
  green_color=$(tput setaf 2)
  reset_color=$(tput sgr0)
else
  red_color=
  green_color=
  reset_color=
fi


colorize_flag() {
  local color

  if [ "$1" = 'fail' ]; then
    color="$red_color"
  else
    color="$green_color"
  fi

  printf '%s' "${color}${1}${reset_color}"
}


sql_fmt='SELECT IF(active, "pass", "fail") AS flag FROM dbDb WHERE name = "%s"'

while IFS= read -r line; do
  sql=$(printf "$sql_fmt" "$line")

  flag=$(mysql --skip-column-names dbname -e "$sql")
  [ -z "$flag" ] && flag='fail'

  printf '%-20s%s\n' "$line" "$(colorize_flag "$flag")"
done < file

第一个 block 通过检查文件描述符1(标准输出)是否在终端上打开来检测脚本是否以交互模式运行(请参阅帮助测试) 。如果在终端中打开它,则脚本认为脚本正在交互运行,即标准输出直接连接到用户的终端,而不是通过管道等。对于交互模式,它借助 tput 命令将变量分配给终端颜色代码。

colorize_flag 函数接受一个字符串 ($1) 并根据其值输出应用了颜色代码的字符串。

最后一个 block 逐行读取文件。对于每一行,构建一个 SQL 查询字符串 (sql) 并调用 mysql 命令,并从输出中删除列名称。 mysql 命令的输出通过命令替换的方式分配给 flag。如果"$flag"为空,则将其分配给'fail'$line 和彩色标志被打印到标准输出。

<小时/>

您可以通过管道链接输出来测试非交互模式,例如:

./script | tee -a
<小时/>

我必须警告您,除非值被正确转义,否则将 shell 变量传递到 SQL 查询通常是个坏主意。并且流行的 shell 不提供任何工具来转义 MySQL 字符串。因此,请考虑使用 Perl、PHP 或任何能够安全构建和运行查询的编程语言来运行查询。

另请注意,就性能而言,最好运行单个查询,然后在循环中解析结果集,而不是在循环中运行多个查询,prepared statements 除外。 .

关于mysql - 新手 : unix bash, 嵌套 if 语句,循环结果来自 sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41476444/

相关文章:

mysql - 如何将 REGEXP 与字边界等转义序列一起使用?

PHP mysql 查询不工作

Windows 批处理文件 : how to compare command line argument to an integer

java - 是否需要进行 if(log.isDebugEnabled()) { ... } 检查?

python - 压缩 if 语句以提供更准确的输出

mysql - Web 应用程序可以在我的 Windows 开发盒上运行,但不能在运行 Debian 的服务器上运行

c# - 检查从 MySQL Data Reader 返回的行数

bash - 查找 bash 中第一列中每个不同值的第 n 列中的最大值

linux - 如何在后台同时使用不同参数的循环运行 bash 脚本中的命令,同时格式化输出

bash - 当命令具有变量赋值时,为什么 sudo 会这样,我该怎么办?