我对linux shell脚本很陌生,有一个问题:
1.)为什么命令
test1="leafpad" && coproc exec "$test1"
在bash中工作(命令行,debian衍生linux上的GNUbash 4.4.12),但命令
test1="coproc" && exec "$test1" leafpad
不是吗?错误消息:bash:exec:corproc:未找到。
而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行代码)需要以两种变体执行:作为条件分支的函数,一次由协处理器引导,另一次不是。
所以我想要的是:
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行命令,但我确信这样做会更方便。
如开头所述:只要不涉及协处理,间接命令执行就可以在命令行上执行(也可以在脚本中执行)。我不能让它和粪菌一起工作。
感谢任何帮助和提示。
@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
的顺序以及内置与二进制的比较
CCD_ 25与CCD_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
在此正常工作,则当前外壳将被替换,您将丢失COPROC
阵列,因此不需要coproc
。无论哪种方式,同时使用两者似乎都很奇怪。你真的确定你需要exec
吗?如果是这样的话,我很乐意听到原因。