Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
复杂bash函数:正确用法?_Bash_Function_Pipe - Fatal编程技术网

复杂bash函数:正确用法?

复杂bash函数:正确用法?,bash,function,pipe,Bash,Function,Pipe,我对自动化日常工作感兴趣。直到最近,我的脚本的每一部分都运行顺利。但现在我试图实现zenity,一切都崩溃了。现在我希望你能看看我做错了什么 Soo,说到这里:我有一个残酷的bash脚本,看起来像这样: #!/bin/bash dosomething () { # code echo $1 >> ~/test.txt # For debugging $1 & # ← Important line # more code } main () { # ot


我对自动化日常工作感兴趣。直到最近,我的脚本的每一部分都运行顺利。但现在我试图实现zenity,一切都崩溃了。现在我希望你能看看我做错了什么

Soo,说到这里:我有一个残酷的bash脚本,看起来像这样:

#!/bin/bash

dosomething () {
  # code
  echo $1 >> ~/test.txt # For debugging
  $1 & # ← Important line
  # more code
}

main () {
  # other code
  dosomething "/usr/bin/rsync $rsync_options" # ← Call it "do_1"
  dosomething "/usr/bin/find $findme_path -iname \"*.gpx\" -print0 | xargs -0 $other_command" # ← Call it "do_2"
  # another code
}

( main | (zenity --progress $zenity_options || $still_another_command ) &
应该发生什么:main的输出通过管道传输到zenity(进度条)。main实际上并不执行任何命令,而是使用参数调用dosomething,该参数包含要执行的命令。dosomething执行该命令

实际情况:dosomething的“echo”部分的工作原理与预期一致。执行脚本后,do_1和do_2中的命令将正确显示在~/test.txt中。(如果我在终端中复制并粘贴了~/test.txt的内容,则每个命令都会以预期的结果执行。)
“do_1”的“重要行”会以预期的结果执行。但“do_2”的“重要路线”似乎没有效果。至少,在执行脚本后,我看不到$other_命令的任何效果


我希望你至少能理解我的意思。如果您能告诉我这里出了什么问题,我将不胜感激。

您在哪里定义
$other_command
?另外,请注意,结尾处缺少一个结束括号(
main
打开一个未闭合的括号)。

在哪里定义
$other_命令
?另外,请注意,结尾处缺少一个结束括号(
main
打开一个未闭合的括号)。

简短回答:请参阅

详细回答:当bash解析一行时,它会在进行变量替换之前解析引号和命令分隔符(
|
等);因此,它在函数中运行
$1&
,$1值中的引号和管道永远不会被解析,它们只是作为参数的一部分传递给命令(在本例中为usr/bin/find)。最终结果:它实际上运行的是相当于
/usr/bin/find$findme_path-iname'*.gpx'-print0'|'xargs-0$other_命令“

通常,在这种情况下,我建议将命令作为一系列单词传递(即,让函数运行
“$@”和
,并将其称为
dosomething/usr/bin/find$findme_path-iname”*.gpx“-print0
,但即使这样也不会处理命令中的管道,它仍然会被视为另一个参数

一种可能是使用
eval
。如果可能的话,应该尽量避免这种情况,因为
eval
是创建脚本错误的好方法--大量错误、细微错误、不可理解的错误、安全错误…它为命令行中的所有内容添加了额外的解析层,这意味着,例如,如果您正在尝试对名为
Fred's file.txt的文件进行操作时,会将该撇号作为引号,并且会变得非常混乱。对恰好包含反引号的文件进行操作太可怕了,根本无法想象。基本上,这是个坏消息

在快速查看实际脚本之后,我建议使用多种策略:在shell函数中尽可能隐藏命令复杂性,这样您就不会试图将管道和重定向传递到
dosomething
函数中,然后使用我前面提到的一系列词方法。对于问题中的脚本,我会这样做:

#!/bin/bash

dosomething () {
  # code
  printf "%q " "$@" >> ~/test.txt # this gives a much better idea what's being done than echo $1 would
  "$@" &
  # more code
}

# hide the pipeline in a shell function
find_and_do_something () {
  /usr/bin/find "$1" -iname "*.gpx" -print0 | xargs -0 $other_command
}

main () {
  # other code
  dosomething /usr/bin/rsync $rsync_options
  dosomething find_and_do_something "$findme_path"
  # another code
}

( main | (zenity --progress $zenity_options || $still_another_command ) &
这意味着您的日志文件将不包含正在执行的管道的详细信息,只需查找和执行某个/whatevers/in/findme\u路径即可,但至少它可以工作。

简短回答:请参阅

详细回答:当bash解析一行时,它在进行变量替换之前解析引号和命令分隔符(
等);结果,它在函数中运行
$1&
,$1值中的引号和管道永远不会被解析,它们只是传递给命令(在本例中为usr/bin/find)作为.Net结果参数的一部分:它实际上运行的是相当于
/usr/bin/find$findme_path-iname'*.gpx'-print0'|'xargs-0$other_命令“

通常,在这种情况下,我建议将命令作为一系列单词传递(即,让函数运行
“$@”和
,并将其称为
dosomething/usr/bin/find$findme_path-iname”*.gpx“-print0
,但即使这样也不会处理命令中的管道,它仍然会被视为另一个参数

一种可能是使用
eval
。如果可能的话,应该尽量避免这种情况,因为
eval
是创建脚本错误的好方法--大量错误、细微错误、不可理解的错误、安全错误…它为命令行中的所有内容添加了额外的解析层,这意味着,例如,如果您正在尝试对名为
Fred's file.txt的文件进行操作时,会将该撇号作为引号,并且会变得非常混乱。对恰好包含反引号的文件进行操作太可怕了,根本无法想象。基本上,这是个坏消息

在快速查看实际脚本之后,我建议使用多种策略:在shell函数中尽可能隐藏命令复杂性,这样您就不会试图将管道和重定向传递到
dosomething
函数中,然后使用我前面提到的一系列词方法。对于问题中的脚本,我会这样做:

#!/bin/bash

dosomething () {
  # code
  printf "%q " "$@" >> ~/test.txt # this gives a much better idea what's being done than echo $1 would
  "$@" &
  # more code
}

# hide the pipeline in a shell function
find_and_do_something () {
  /usr/bin/find "$1" -iname "*.gpx" -print0 | xargs -0 $other_command
}

main () {
  # other code
  dosomething /usr/bin/rsync $rsync_options
  dosomething find_and_do_something "$findme_path"
  # another code
}

( main | (zenity --progress $zenity_options || $still_another_command ) &

这意味着您的日志文件将不会包含正在执行的管道的详细信息,只需
查找和执行某件事/whatevers/in/findme\u path
,但至少它会工作。

感谢您的快速回复。我没有在这里复制并粘贴我的真实代码–太长了。很抱歉,忘记了这里的括号。如果我复制并粘贴了该部分,则在do_2中的部分(在do_某事之后)进入终端后,一切都正常运行。打开shell调试,即
set-vx
。然后您可能会看到vars或其他语法没有按您认为的那样运行。还有一些编写器