间接 bash 命令执行未按预期使用 coproc
indirect bash command execution not working as expected with coproc
我是 linux shell 脚本编写的新手,有一个问题:
1.) 为什么命令
test1="leafpad" && coproc exec "$test1"
在 bash 中工作(命令行,GNU bash 4.4.12 在 debian 衍生版 linux 上),但是命令
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
和更多变体,但其中 none 有效。
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
它也因错误消息“未找到”而停止。不同的引用方式并没有解决它,只是产生了不同的错误信息。我没能找到这个任务的正确引用。如何正确阅读此 qouting?
当然我可以在代码中重复 6 行命令,但我很确定这样做会更方便。
如开头所述:间接命令执行适用于命令行(也适用于脚本),只要不涉及 coproc。我无法让它与 coproc 一起工作。
感谢任何帮助和提示。
@Socowi 第一次回答后更新:
感谢您全面而快速的回答,Socowi。关于 coproc
不是命令,你显然是对的。所以我现在明白为什么我的尝试不得不失败了。 exec
命令仅在我的实验期间添加。我没有这个就开始了,但是在没有成功之后我认为它会有所帮助。这只是一种绝望的行为。 my_command=`lengthy command with some arguments $arg1 $arg2 ...`
行中的反引号是一个拼写错误,正如您所指出的,应该有正常的引号,因为我当然打算在 if
中执行命令。我可能会按照您指示的方式前进,在脚本中使用 function {...}
。但是同时对这个问题进行了实验,我得出了一个惊人的解决方案:对我来说令人惊讶,因为 coproc
不是一个命令和 leafpad
之间的区别是它的二进制命令。所以应该清楚 test1='coproc' && test2='leafpad' && "$test1 $test2"
将失败并显示错误消息 bash: coproc leafpad: command not found.
,这是事实。但是现在:为什么 test1='coproc' && test2='leafpad' && /bin/bash -c "$test1 $test2"
会做这个工作,启动 leafpad,允许在 bash 中并行输入更多命令,就像我只输入 leafpad &
一样?但是这次 从变量 执行内置函数(或关键字?)和命令,当试图在第一个 bash 实例中直接输入它时被拒绝。 bash 的第一个实例是正确的,第二个实例也应该是正确的,或者我的观点是错误的?为什么会这样? -c
选项除了执行命令之外还有其他作用吗?
引用是不是这里的问题。还有另外两个问题:
exec
和 coproc
的顺序以及内置函数与二进制文件的顺序
test1="leafpad" && coproc exec "$test1"
等同于 coproc exec leafpad
.
test1="coproc" && exec "$test1" leafpad
等同于 exec coproc leafpad
.
顺序不同:coproc exec
与 exec 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
?
话虽如此,我真的很想知道 coproc
和 exec
的组合。在我看来,coproc exec cmd
似乎忽略了 exec
部分,与 coproc cmd
相同。如果 exec
在这里正常运行,当前的 shell 将被替换,您将丢失 COPROC
数组,因此不需要 coproc
。无论哪种方式,同时使用两者似乎都 st运行ge。你真的确定你需要 exec
吗?如果是这样,我很乐意听到原因。
我是 linux shell 脚本编写的新手,有一个问题:
1.) 为什么命令
test1="leafpad" && coproc exec "$test1"
在 bash 中工作(命令行,GNU bash 4.4.12 在 debian 衍生版 linux 上),但是命令
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
和更多变体,但其中 none 有效。
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
它也因错误消息“未找到”而停止。不同的引用方式并没有解决它,只是产生了不同的错误信息。我没能找到这个任务的正确引用。如何正确阅读此 qouting?
当然我可以在代码中重复 6 行命令,但我很确定这样做会更方便。
如开头所述:间接命令执行适用于命令行(也适用于脚本),只要不涉及 coproc。我无法让它与 coproc 一起工作。
感谢任何帮助和提示。
@Socowi 第一次回答后更新:
感谢您全面而快速的回答,Socowi。关于 coproc
不是命令,你显然是对的。所以我现在明白为什么我的尝试不得不失败了。 exec
命令仅在我的实验期间添加。我没有这个就开始了,但是在没有成功之后我认为它会有所帮助。这只是一种绝望的行为。 my_command=`lengthy command with some arguments $arg1 $arg2 ...`
行中的反引号是一个拼写错误,正如您所指出的,应该有正常的引号,因为我当然打算在 if
中执行命令。我可能会按照您指示的方式前进,在脚本中使用 function {...}
。但是同时对这个问题进行了实验,我得出了一个惊人的解决方案:对我来说令人惊讶,因为 coproc
不是一个命令和 leafpad
之间的区别是它的二进制命令。所以应该清楚 test1='coproc' && test2='leafpad' && "$test1 $test2"
将失败并显示错误消息 bash: coproc leafpad: command not found.
,这是事实。但是现在:为什么 test1='coproc' && test2='leafpad' && /bin/bash -c "$test1 $test2"
会做这个工作,启动 leafpad,允许在 bash 中并行输入更多命令,就像我只输入 leafpad &
一样?但是这次 从变量 执行内置函数(或关键字?)和命令,当试图在第一个 bash 实例中直接输入它时被拒绝。 bash 的第一个实例是正确的,第二个实例也应该是正确的,或者我的观点是错误的?为什么会这样? -c
选项除了执行命令之外还有其他作用吗?
引用是不是这里的问题。还有另外两个问题:
exec
和 coproc
的顺序以及内置函数与二进制文件的顺序
test1="leafpad" && coproc exec "$test1"
等同于 coproc exec leafpad
.
test1="coproc" && exec "$test1" leafpad
等同于 exec coproc leafpad
.
顺序不同:coproc exec
与 exec 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
?
话虽如此,我真的很想知道 coproc
和 exec
的组合。在我看来,coproc exec cmd
似乎忽略了 exec
部分,与 coproc cmd
相同。如果 exec
在这里正常运行,当前的 shell 将被替换,您将丢失 COPROC
数组,因此不需要 coproc
。无论哪种方式,同时使用两者似乎都 st运行ge。你真的确定你需要 exec
吗?如果是这样,我很乐意听到原因。