管道中的循环对Solaris / bin / sh有副作用,但不对Linux有影响

时间:2016-01-14 17:22:46

标签: linux sh solaris subshell

我在Linux下和solaris下运行相同的脚本。 这是脚本:

#!/bin/sh
index=0

ls /tmp | grep e |
while read fileWithE
do
    echo $fileWithE
    index=`expr $index + 1`
done
echo "index is $index"

由于while循环在子shell中运行,我期待' index是0'作为solaris和linux的输出。 但在solaris中,$ index是包含' e'的文件的实际数量。在/ tmp下。 那么虽然循环不能在solaris下的子shell中运行?我在两个操作系统中都期待相同的结果。?

1 个答案:

答案 0 :(得分:5)

POSIX不要求管道的任何组件都不由外壳运行;这是一个留给单个shell的作者的实现决定,因此shell可能有任何组件或没有父shell调用的管道组件(因此能够产生超出生命周期的副作用)管道)并且仍然符合POSIX sh。

已知使用父shell执行管道的最后一个组件的shell包括:

  • ksh88
  • ksh93的
  • 的zsh
  • bash 4.2,启用lastpipe选项,禁用作业控制。

如果您想确定在管道中运行的shell命令对所有符合POSIX的shell都没有副作用,那么将整个管道放在显式子shell中是明智的。

您可以通过实验验证这种行为差异与管道中的位置相关的一种方法是通过添加额外的管道元素来稍微修改您的测试。

#!/bin/sh

index=0
ls /tmp \
  | grep e \
  | while read fileWithE; do echo "$fileWithE"; index=`expr $index + 1`; done \
  | cat >/dev/null
echo $index

...您会看到| cat更改行为,例如index循环对while所做的更改在调用shell中不再可见即使在常见的炮弹上也是如此。