【问题标题】:Here document as an argument to bash function这里文档作为 bash 函数的参数
【发布时间】:2011-06-07 13:06:16
【问题描述】:

是否可以将here文档作为bash函数参数传递,并在函数中将参数保留为多行变量?

大致如下:

function printArgs {
echo arg1="$1"
echo -n arg2=
cat <<EOF
$2
EOF
}

printArgs 17 <<EOF
18
19
EOF

或者也许:

printArgs 17 $(cat <<EOF
18
19
EOF)

我有一个此处的文档,我想将它作为要执行的命令提供给 ssh,并且从 bash 函数调用 ssh 会话。

【问题讨论】:

    标签: bash function shell arguments heredoc


    【解决方案1】:

    可能的方法是:

    printArgs 17 "$(cat <<EOF
    18
    19
    EOF
    )"
    

    但是为什么要为此使用heredoc? heredoc 在参数中被视为文件,因此您必须(ab)使用cat 来获取文件的内容,为什么不这样做:

    print Args 17 "18
    19"
    

    请记住,最好在您要 ssh 到的机器上创建一个脚本并运行该脚本,然后尝试像这样的一些 hack,因为 bash 仍会在您的多行参数中扩展变量等。

    【讨论】:

    • 也许EOF(" 之间应该有一个换行符?
    • 我想传递一个大而丑陋的表格让 Emacs 以批处理模式进行评估;这是这个“黑客”的完美用例。
    • 几个月后,我需要为 GIMP 传递一个大而丑陋的表格,以便在其 TinyScheme 批处理处理器中进行评估。它似乎不断出现
    • 请注意,您可以在 heredocs 中使用 &lt;&lt;"EOF" 而不是 &lt;&lt;EOF 来抑制变量扩展。
    • 回答为什么这是有帮助的:HEREDOC 允许我在字符串中同时使用 " 和 ' 而不会转义引号。
    【解决方案2】:

    如果您不使用会吸收标准输入的东西,那么您将不得不提供一些东西:

    $ foo () { while read -r line; do var+=$line; done; }
    $ foo <<EOF
    a
    b
    c
    EOF
    

    【讨论】:

    • 仅供参考。您也可以在函数中执行“cat /dev/stdin”,而不是使用“while”进行迭代
    • 虽然这在原则上是正确的,但它会吃掉换行符,需要为每个新的$line 附加换行符。此外,变量应初始化为local
    【解决方案3】:

    基于 Ned 的回答,我的解决方案允许函数将其输入作为参数列表或 heredoc。

    printArgs() (
      [[ $# -gt 0 ]] && exec <<< $*
      ssh -T remotehost
    )
    

    所以你可以这样做

    printArgs uname
    

    或者这个

    printArgs << EOF
    uname
    uptime
    EOF
    

    因此,您可以将第一种形式用于单个命令,将长形式用于多个命令。

    【讨论】:

    • 可爱。非常非常可爱。
    • 我想我需要更新一下exec。在您的示例中,这些命令似乎将在本地计算机上执行,而不是在远程计算机上执行。 @starfry
    • 它们肯定在远程机器上执行(将remotehost 替换为您可以访问并尝试上述示例的真实内容)。以防万一您的外壳有所不同,请使用bash(根据原始问题)。如果您的外壳确实有所作为,可能值得在此处添加注释。
    • @mattalxndr 如果exec 没有command 参数(就像这里的情况),任何应用到它的stdio 重定向都将应用到当前shell,即在这里应用也到以下ssh 行。换句话说, exec 将扩展的 $* 提供给 ssh 的标准输入。然而,这种方法的缺点是您可能会从 remotehost 显示 motd 问候语,因为 ssh 运行的是交互式登录 shell,而不是命令。
    • 我明白了,所以它正在输入标准输入。很有趣。
    【解决方案4】:

    xargs 应该做你想做的事。它将标准输入转换为命令的参数(注意 -0 允许保留换行符)

    $ xargs -0 <<EOF printArgs 17
    18
    19
    EOF
    

    但对于你的特殊情况,我建议你在 ssh 的标准输入上发送命令:

    $ ssh host <<EOF
    ls
    EOF
    

    【讨论】:

    • xargs 不能调用 shell 函数,因为它使用了execve()。因此,问题中的“bash 函数”约束是相关的——使用常规命令进行测试是行不通的。
    • @CharlesDuffy 好收获
    【解决方案5】:

    通过此处的文档和函数向 ssh 提供命令的一种方法如下:

    #!/bin/sh
    # define the function
    printArgs() {
    echo "$1"
    ssh -T remotehost
    }
    # call it with a here document supplying its standard input
    printArgs 17 <<EOF
    uname
    uptime
    EOF
    

    结果:

    17
    Linux remotehost 2.6.32-5-686 ...
    Last login: ...
    No mail.
    Linux
     16:46:50 up 4 days, 17:31,  0 users,  load average: 0.06, 0.04, 0.01
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      • 2014-02-08
      • 1970-01-01
      • 2023-04-10
      • 2017-12-27
      相关资源
      最近更新 更多