我想创建 scipt 以促进从 Hive 生成本地文本文件提取。这基本上是执行如下命令:
hive -e "SET hive.cli.print.header=true;SELECT * FROM dropme"|perl -pe 's/(?:\t|^)\KNULL(?=\t|$)//g'>extract/outbound/dropme.txt
虽然上面的工作就像一个魅力,但我发现通过参数化的以下脚本(非常简化)实现它非常有问题:
#!/bin/sh
TNAME=dropme
SQL="SELECT * FROM $TNAME"
echo $SQL
echo "SQL: $SQL"
EXTRACMD="hive -e \"SET hive.cli.print.header=true;$SQL\"|perl -pe 'BEGIN{if(defined(\$_=<ARGV>)){s/\b\w+\.//g;print}}s/(?:\t|^)\KNULL(?=\t|$)//g'>extract/outbound/$TNAME.txt"
echo "CMD: $EXTRACMD";
${EXTRACMD}
运行时我得到:Exception in thread "main" java.lang.NumberFormatException: For input string: "e"
我知道您可以打印文本或执行命令的方式有很多种。例如,该行echo $SQL
打印了我目录中的文件列表:
SELECT file1.txt file2.txt file3.txt file4.txt FROM dropme
而下一个:echo "SQL: $SQL"
给出了我想要的:SQL: SELECT * FROM dropme
echo "CMD: $EXTRACMD"
打印(几乎)要执行的命令。几乎,正如我\t
在 perl 代码中看到的那样:
CMD: hive -e "SET hive.cli.print.header=true;SELECT * FROM dropme"|perl -pe 'BEGIN{if(defined($_=<ARGV>)){s\w+\.//g;print}}s/(?: |^)\KNULL(?= |$)//g'>extract/outbound/dropme.txt
也许这仍然可以,但我想要的是能够将此命令复制并粘贴到(其他)终端并按照我放在顶部的命令执行。理想情况下,我希望该命令完全相同(所以在\t
那里)
当我尝试执行它时,我遇到的最大问题是(${EXTRACMD}
行)。我收到错误:
Exception in thread "main" java.lang.NumberFormatException: For input string: "e"
…等等,因为 bash 在这里将每个“单词”都视为单个命令,这与此无关。我假设我什至不知道真正尝试运行的是什么(之前的打印尝试显然没有帮助)
我知道我有多种选择,例如:
- 转义命令定义字符串中的特殊字符(就像我对双引号所做的那样)
- 试验 echo 和
$VAR
,'$VAR'
或"$VAR"
- 试验“${EXTRACMD}”或通过评估
eval "${EXTRACMD}"
- 试验
shopt -s extglob
或set -f
但是由于组合的数量非常多,并且以我的小 bash 经验,我觉得最好在这里寻求良好的做法,所以我的问题是:
有没有办法先打印(复杂/复合外壳)命令,然后能够执行它(完全按照打印输出)?在这种情况下,它将从顶部打印确切的命令,然后以与手动将该输出复制到终端提示符并按相同的方式执行它Enter。