如何将 else 用于 `ifne`?

如何将 else 用于 `ifne`?

ifne- 如果标准输入不为空则运行命令

如果可能的话,如果标准输入也为空,我想运行命令;的其他部分ifne

$ printf "hello" | ifne echo "world" 
world

在这里,如果标准输入为空,我想以不同的语句结束。

$ printf "" | ifne echo "world" || echo "else"但它什么也没打印。有可能elseifne

答案1

( ifne -n sh -c 'exec >&3; echo else' | ifne echo world ) 3>&1

如果标准输入不为空,则ifne -n不会运行sh …,它的行为就像cat将输入传递给第二个ifne。第二个ifne将运行echo world。这非常简单。

如果标准输入为空,ifne -n则将运行sh …。我们不能只使用,ifne -n echo else | …因为这样else就会到达第二个ifne,我们也会得到world。因此,我们3>&1甚至在之前就可以使用整个片段的标准输出|。它可用作文件描述符 3.ifne -n echo else >&3 | …会打破非空输入的情况,其中数据必须从ifne -nifne。为了得到我们想要的东西,我们需要重定向,echo但不需要重定向ifne -n本身;因此是内壳。

您可以echo else用其他命令替换。您可以替换为另一个命令(如果您需要多个命令,则echo word可能是这样)。sh -c …我的观点是这个答案不依赖于else或被world打印;替代者可能会沉默,也可能不会沉默,这并不重要。

答案2

从手册页:

-n 反向操作。如果标准输入为空,则运行该命令。请注意,如果标准输入不为空,则在这种情况下将通过 ifne 传递。

$ printf "not-empty\n" | ifne    printf "This will print\n"
This will print
$ printf ""            | ifne    printf "This will not print\n"
$ printf "not-empty\n" | ifne -n printf "This will not print\n"
not-empty
$ printf ""            | ifne -n printf "This will print\n"
This will print

这可以让您执行以下操作:

$ dosoemthing | ifne -n printf "There was no output"

如果您正在寻找 if-then-else 类型的解决方案,您可以将 stdout 通过管道传输到teecan call 的两个实例ifne

$ printf "if\n" | tee >(ifne printf "then\n") | ifne -n printf "else\n"
if
then
$ printf ""     | tee >(ifne printf "then\n") | ifne -n printf "else\n"
else

但您也可以打印原始的标准输出。这就是通过这个ifne -n过程。

答案3

作为对现有答案的补充,请注意,它的ifne工作原理是尝试从标准输入读取,如果有东西到来,它会启动命令并通过管道循环将数据铲入其中。

然而,对于大多数类型的输入,应该可以检测是否有某些输入而无需读取它,这将节省提取处理并避免管道。

例如,您可以定义:

input_available() {
  perl -MIO::Poll -e '
    $p = IO::Poll->new;
    $p->mask(STDIN, POLLIN);
    $p->poll or die "poll: $!\n";
    exit(1) unless $p->events(STDIN) & POLLIN;
    require "sys/ioctl.ph";
    $n = pack("L", 0);
    ioctl(STDIN, &FIONREAD, $n) or die"ioctl: $!\n";
    $n = unpack("L", $n);
    exit(1) unless $n > 0'
}

然后,你可以这样做:

some-command |
  if input_available; then
    echo Input available:
    cat
  else
    echo No input available
  fi

poll()在 Linux 上,POLLIN仅当存在一些数据时才会在管道上进行标记,但并非所有系统都是如此,因为有些系统还在文件末尾标记 POLLIN。因此,FIONREAD ioctl 检查是否确实有数据。该 ioctl 不适用于所有类型的输入。例如在 Linux 上,我发现它不适用于/dev/null.但至少它确实可以在常规文件、管道和 tty 设备上工作。

答案4

管道

somecommand | ifne echo something

...如果写入标准输出,则产生输出(字符串something) 。somecommand

如果管道没有产生任何输出,那么somecommand就没有产生任何输出。这可以通过以下方式捕获ifne -n

somecommand | ifne echo something | ifne -n echo nothing

测试:

$ printf 'ok' | ifne echo something | ifne -n echo nothing
something
$ printf '' | ifne echo something | ifne -n echo nothing
nothing

请注意,这会丢弃管道中最左侧命令的输出。这可以通过使用类似的东西来解决

ifne sh -c 'cat;echo something'

...作为管道的第二个命令,其中cat是应接收左侧输出的任何命令。

这还依赖于这样一个事实:在第一个命令不产生任何输出的情况下,最后一个命令没有给出任何输入。

相关内容