ifne
- 如果标准输入不为空则运行命令
如果可能的话,如果标准输入也为空,我想运行命令;的其他部分ifne
。
$ printf "hello" | ifne echo "world"
world
在这里,如果标准输入为空,我想以不同的语句结束。
$ printf "" | ifne echo "world" || echo "else"
但它什么也没打印。有可能else
吗ifne
?
答案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 -n
到ifne
。为了得到我们想要的东西,我们需要重定向,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 通过管道传输到tee
can 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
是应接收左侧输出的任何命令。
这还依赖于这样一个事实:在第一个命令不产生任何输出的情况下,最后一个命令没有给出任何输入。