【问题标题】:indirect bash command execution not working as expected with coproc间接 bash 命令执行无法与 coproc 一起按预期工作
【发布时间】:2021-02-20 21:14:35
【问题描述】:

我是 linux shell 脚本的新手,有一个问题:

1.) 为什么命令

test1="leafpad" && coproc exec "$test1"

在 bash 中工作(命令行,在 debian 衍生版 linux 上使用 GNU bash 4.4.12),但是命令

test1="coproc" && exec "$test1" leafpad

没有?错误信息: bash: exec: coproc: 未找到。

coproc leafpad 确实按预期工作。

如何正确引用此命令才能使其工作?我已经试过了

test1=`coproc` && exec "$test1" leafpad

test1='coproc' && exec "$test1" leafpad

test1="'coproc'" && exec "$test1" leafpad

test1=`coproc` && exec '$test1' leafpad

test1=`coproc` && exec `$test1` leafpad

test1="coproc" && exec $test1 leafpad

test1=`coproc` && exec $test1 leafpad

还有一些变体,但它们都不起作用。

2.) 这只是命令行测试。但我更需要的是在脚本中执行此操作:所以我确信需要做一些额外的引用或伪装特殊字符。

背景: 我必须执行一个命令,其中包含许多参数,其中一些被变量替换。想想像 yad 这样的东西,它的所有可能参数都在几行中,但让我们创建一个更简单的例子:

my_codeset="437"
my_line="20"
my_filename="somthing.txt"
if [ $value == 0 ]; then my_tabwidth='--tab-width=10'; else my_tabwidth=""; fi   # set tabs or not

leafpad --codeset="$my_codeset" "$my_tabwidth" --jump="$my_line" "$my_filename"

其中给定的变量是变化的主题,作为之前用户交互的函数。

现在这个完整的命令(原来是大约 6 行代码),需要在两个变体中执行: 一次由 coproc 领导,另一次则不是,作为条件分支的函数。

所以我想要的是:

if [ $something == 1 ]; then copr_this="coproc"; else copr_this=""; fi

exec '$copr_this' <mycommand, with all its quoted arguments>

而不是

if [ something == 0]; then
          lengthy command here
else
          coproc lengthy command here, exactly repeated.
fi

我已经尝试过另一种方式来管理它,即将完整的冗长命令放在一个变量中,并在条件分支中执行它:

my_command=`lengthy command with some arguments $arg1 $arg2 ...`

if...
      exec "$my_command"
else
      coproc exec "$my_command"
fi

它也因错误消息“未找到”而停止。不同的引用方式并没有解决它,而只会产生不同的错误消息。我没能找到这个任务的正确引用。如何正确阅读此引用?

当然我可以重复代码中的 6 行命令,但我很确定这样做会更方便。

如开头所述:间接命令执行可在命令行(也可在脚本内)运行,只要不涉及 coproc。我无法让它与 coproc 一起使用。

感谢任何帮助和提示。


@Socowi 第一次回答后更新:

感谢您提供全面而快速的答复,Socowi。你对coproc 不是一个命令显然是正确的。所以我现在明白为什么我的尝试必须失败。 exec 命令仅在我的实验期间添加。我开始时没有这个,但在没有成功之后,我认为它会有所帮助。这只是一种绝望的行为。 my_command=`lengthy command with some arguments $arg1 $arg2 ...` 行中的反向引号是一个错字,应该有正常的引号,正如你所指出的,因为我当然打算在 if 内执行命令。我可能会按照您指示我的方式前往,在脚本中使用function {...}。但与此同时,在对这个问题进行了实验之后,我得出了一个令人惊讶的解决方案:对我来说太惊讶了,因为coproc 不是命令和leafpad 之间的区别在于它的二进制命令。所以应该清楚test1='coproc' &amp;&amp; test2='leafpad' &amp;&amp; "$test1 $test2" 将失败并显示错误消息bash: coproc leafpad: command not found.,这是真的。但是现在:为什么test1='coproc' &amp;&amp; test2='leafpad' &amp;&amp; /bin/bash -c "$test1 $test2" 会完成这项工作,启动leafpad,允许在bash 中并行输入更多命令,就像我只输入leafpad &amp; 一样?但是这一次从变量中同时执行内置函数(或关键字?)和命令,当尝试直接在第一个 bash 实例中输入它时被拒绝。 bash 的第一个实例是正确的,第二个实例也应该是正确的,还是我有一个错误的观点?为什么它会这样工作? -c 选项除了执行命令还有其他作用吗?

【问题讨论】:

    标签: bash shell command-substitution coproc


    【解决方案1】:

    引用不是这里的问题。还有两个问题:

    execcoproc 的顺序以及内置与二进制文件的顺序

    test1="leafpad" &amp;&amp; coproc exec "$test1"coproc exec leafpad 相同。
    test1="coproc" &amp;&amp; exec "$test1" leafpadexec coproc leafpad 相同。

    顺序有所不同:coproc execexec coproc。后者不起作用,因为exec 将当前shell 替换为指定的程序。但是,coproc 是一个内置命令。您的系统上没有 coproc 二进制文件。您只能从bash 内部运行它。因此exec 失败。

    命令替换与字符串

    在你的脚本中...

    my_command=`lengthy command`
    if ...; then
          exec "$my_command"
    else
          coproc exec "$my_command"
    fi
    

    ...您没有将lengthy command 存储在变量中,但是您运行了该命令并将其输出(v=`cmd` v=$(cmd) 相同)存储在if 之前。然后在 if 中,您尝试将命令的输出作为另一个命令执行。

    要将命令存储为字符串并稍后执行,您可以使用my_command="lengthy command"; $my_command(注意故意缺少引号)。但是,bash 提供了更好的方法来存储命令。使用数组或函数代替字符串。这里我们使用一个函数:

    my_command() {
      exec lengthy command
    }
    
    if ...; then
       coproc my_command
    else
       my_command
    fi
    

    coproc exec?

    话虽如此,我真的很想知道coprocexec 的组合。对我来说,coproc exec cmd 似乎忽略了exec 部分并且与coproc cmd 相同。如果exec 在这里正常运行,当前的shell 将被替换,您将丢失COPROC 数组,因此不需要coproc。无论哪种方式,同时使用两者似乎很奇怪。你真的确定你需要那个exec吗?如果是这样,我很乐意听到原因。

    【讨论】:

    • 我没有测试太多,但coproc exec something 似乎只相当于coproc something——exec 发生在一个子shell 中,(给定一个简单的命令)将执行无论如何命令。但是还有另一个复杂的问题:coproc 不是内置函数,它是一个关键字,这意味着它需要在变量扩展之前被识别,所以即使没有 exec,它也无法工作。
    • @Gordon Davisson:“即使没有 exec,它也无法工作” 我也发现了。我不得不更新问题,因为出于某种原因,系统不允许我将其添加为评论。
    • @GordonDavisson 谢谢。你应该添加一个答案。我很乐意为你投票。到目前为止,我从未想过关键字和内置函数之间的这种区别。
    猜你喜欢
    • 1970-01-01
    • 2014-11-28
    • 1970-01-01
    • 2012-02-19
    • 2019-12-14
    • 1970-01-01
    • 2012-04-11
    • 2019-07-31
    • 1970-01-01
    相关资源
    最近更新 更多