在没有子shell的情况下遍历bash中命令的输出


9

我想遍历命令的输出而不创建子外壳或使用临时文件。

我的脚本的初始版本看起来像这样,但这不起作用,因为它创建了一个子外壳,并且该exit命令终止了该子外壳,而不是所需的主脚本。它是配置策略路由的更大脚本的一部分,如果它检测到会导致路由失败的条件,则将暂停执行。

sysctl -a 2>/dev/null | grep '\.rp_filter' | while read -r -a RPSTAT ; do

  if [[ "0" != "${RPSTAT[2]}" ]] ; then
    echo >&2 "RP Filter must be disabled on all interfaces!"
    echo >&2 "The RP filter feature is incompatible with policy routing"
    exit 1
  fi
done

因此,建议的替代方法之一是使用类似这样的命令来避免子外壳。

while read BLAH ; do echo $BLAH; done </root/regularfile

所以在我看来,我也应该可以使用这样的命令来避免子shell并仍然从我想要的程序中获取输出。

while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')

不幸的是,使用该命令会导致此错误。

-bash: syntax error near unexpected token `<(sysct ...

我真的很困惑,因为这行得通。

cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')

我可以将该命令的输出保存到一个临时文件中,并使用重定向该临时文件,但是我想避免这样做。

那么,为什么重定向给我一个错误,除了创建临时文件之外,我还有其他选择吗?


Answers:


13

您错过了<。应该:

while read BLAH ; do echo $BLAH; done < <(sysctl -a 2>/dev/null | grep '\.rp_filter')

认为<(sysctl -a 2>/dev/null | grep '\.rp_filter')是一个文件。


非常感谢。仅仅出于我的启发,能否将我指向记录此内容的手册页,帮助或网页?在尝试搜索时,我无法让Google向我指出任何有用的信息。
Zoredache


应该注意的是,<()替换使用文件描述符,并且在某些操作系统上将透明地创建和使用临时文件。
ewindisch 2011年

@Zoredache:只需<(在bash手册中进行搜索即可(位于“流程替代”下)。
吉尔(Gilles)“所以,别再邪恶了”,

@ewindisch,如果一个工具透明地创建了一个临时文件,那么当我确定不需要时,我只是不想手动创建一个。
Zoredache

0

如果有人再次来这里还有其他选择...

根据外壳程序的不同,您可能会set -o errexit在命令(包括子外壳程序)退出非零而不会陷入if块或结尾&&或的情况下使父外壳程序退出||,例如

/bin/false || echo "ignoring error"

或者,您可以使用kill和$ PPID环境变量(如果可用)使子shell向父级发出信号。

或者,您可以将while块移到函数中并返回0/1(在while块之后显式返回0),然后像执行管道一样sysctl | grep | function || exit。我想您也可以将返回值放在内联代码块中,但是函数是您的朋友。;)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.