如何在shell脚本中使用双管道执行多个命令

4

我正在编写一个Korn shell脚本,其中有一个函数如下:

#!/bin/ksh
myfunc() {
    some_command1 || return 1
    some_command2 || return 1
    ...
}

我使用双竖线和返回语句,以便函数在命令失败时立即返回。

但我也希望它在返回之前打印一些错误消息,我尝试过:

#!/bin/ksh
myfunc() {
    some_command1 || echo "error while doing some_command1"; return 1
    some_command2 || echo "error while doing some_command2"; return 1
    ...
}

但这并不起作用,第一条返回语句总是会被执行,无论 some_command1 是否成功。

而且

#!/bin/ksh
myfunc() {
    some_command1 || (echo "error while doing some_command1"; return 1)
    some_command2 || (echo "error while doing some_command2"; return 1)
    ...
}

似乎并不起作用,它似乎只从子进程返回而不是函数,some_command2无论some_command1成功还是失败都会被执行。

有没有一种方法可以将语句echo "error while doing some_command2"; return 1分组,使它们仅在前一个命令失败时一起执行。


2
{ cmd1; cmd2; } 可能吗? - Mark Setchell
我喜欢那个函数的风格 - 首先处理异常,避免嵌套的if语句。 - Henk Langeveld
1个回答

12

简单明了的方法是使用{ ...; ...; },这将命令组合在一起而不创建子shell。

some_command1 ||
    { echo "error while doing some_command1"; return 1; }

虽然我建议使用标准错误输出来输出错误信息:

some_command1 ||
    { echo "error while doing some_command1" >& 2; return 1; }

只是因为我可以,我会告诉你我的秘密快捷方式:

some_command1 ||
    return 1 $(echo "error while doing some_command1" >& 2)

最后一部分虽然不太常规,但仍是可移植的POSIX shell。


1
不知何故,解决方案#1和#2对我无效,就像没有花括号存在一样,总是执行return 1。但是第三个解决方案非常有效。 - asinkxcoswt
1
抱歉,我刚刚才发现为什么解决方案#1和#2对我无效,因为我写成了这样:{echo "444"; return 1},在return 1后面没有分号。这使得返回语句每次都会执行。 - asinkxcoswt
4
@asinkxcoswt,{} 必须 在它们周围有空格。请参考 https://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping。 - glenn jackman
1
@asinkxcoswt 正如Glenn所说,(...){...}不能互换,因为括号不需要任何空格,而花括号则需要。 @glennjackman 一如既往,感谢您提供的详细信息。 - Henk Langeveld

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接