bash 在变量扩展期间向 > (重定向)添加单引号(破坏我的重定向)

bash 在变量扩展期间向 > (重定向)添加单引号(破坏我的重定向)

经过研究,我不确定这在 bash 脚本中是否可行。我发现最可能的原因是 bash 的 shell 扩展顺序。 (或许?)

我希望发生什么, 能够>通过先前的变量启用/禁用语句的重定向 ( )。

例如:下面的 printf 输出应该>根据变量$SendGrafana包含的内容进行(重定向)。
但是这个示例代码不起作用:

SendGrafana=" > /dev/tcp/192.168.1.242/5062"

awk -v vars="$vars" 'BEGIN{printf "output.api %s \n", vars;}' $SendGrafana

我希望上面的代码能像这样工作:

awk -v vars="$vars" 'BEGIN{printf "output.api %s \n", vars;}' > /dev/tcp/192.168.1.242/5062

另外-当我使用 set -x (用于调试)运行脚本时,我看到单引号 (') 仅围绕重定向 (>) ,我认为这是问题所在,因为没有任何内容发送到我的 netcat 侦听器。我读到这只是为了用户使用 set -x 时的可读性,但是问题仍然存在。

以下是启用 set -x 时的相关输出:

+ awk -v vars=3 'BEGIN{printf "output.api %s \n", vars;}' '>' /dev/tcp/192.168.1.242/5062

(注意“>”)

我尝试了很多方法,无论是在变量声明还是变量扩展,但在调用脚本时都无法将输出重定向到 192.168.1.242:5062。谢谢


编辑如下- (在我的评论中添加这部分,因为我试图使问题简短,但建议应该在这里):

添加更多上下文:我什至使用这个$SendGrafana变量的原因,而不是没有变量并且> /dev/tcp/192.168.1.242/5062在每个 awk 语句之后逐字逐句 - 是这样我可以轻松设置$SendGrafana= " ",并且我的脚本将输出到 STDOUT (而不是通过 发送到 192.168.1.242 > /dev/tcp/192.168.1.242/5062) 。我仅在调试/测试添加新语句期间需要 STDOUT 上的输出。

答案1

问题确实是评估顺序。

这只是将文本放入命令行:shell 来实现重定向已经太晚了。

paul $ j=" > foo.txt "
paul $ echo Words Here $j
Words Here > foo.txt
paul $ ls -l foo.txt
ls: cannot access 'foo.txt': No such file or directory

这会导致 shell 重新评估整个命令。

paul $ eval echo Words Here $j
paul $ ls -l foo.txt
-rw-r--r-- 1 paul paul 11 Aug 19 22:38 foo.txt
paul $ cat foo.txt
Words Here
paul $ 

内置的 eval 可能很难正确使用,因此我尽可能避免使用它。您的命令会被评估两次(一次作为 eval 的参数,另一次由 eval 本身),这可能会使您的引用变得困难和乏味(特别是在涉及 awk 的情况下,已经需要单引号和双引号。)此外,错误可能会导致您的作为命令执行的变量,会产生意想不到的后果。更多这里:

unix.stackexchange.com/questions/278427/why-and-when-should-eval-use-be-avoided-in-shell-scripts

添加的示例:

我发布的 StackExchange 链接中的一个建议是让 shell 创建一个新的文件描述符,然后首先将其定向到目标。

这是一个有点夸张的测试脚本。

#! /bin/bash

#.. First arg to script is -l for test runs.

#.. For your live action.
Grafana="/dev/tcp/192.168.1.242/5062"

#.. For my demo here.
Grafana="./foo.txt"

rm -f foo.txt

if [[ "${1}" = "-l" ]]; then
    exec 7>&1
    shift 1
else
    exec 7>"${Grafana}"
fi  
 
vars="${@}" #.. Rest of args to output.

awk -v vars="$vars" 'BEGIN{printf "output.api %s \n", vars;}' 1>&7

ls -l foo.txt && cat foo.txt

并进行测试,记录到终端,然后记录到命名文件/设备。

Paul--) ./Swit -l Easy Living
output.api Easy Living 
ls: cannot access 'foo.txt': No such file or directory
Paul--) ./Swit Easy Living
-rw-r--r-- 1 paul paul 24 Aug 20 09:22 foo.txt
output.api Easy Living 
Paul--) 

您可以将 fd 7 保持打开状态,并在脚本中多次使用它。你可以用以下命令关闭它exec 7>&-

相关内容