| 和 || 有什么区别?
当我运行此命令时:
ls -la | id
我得到的结果是id
当我运行此命令时:
ls -la || id
我得到的结果是ls -la
那么它们之间有什么区别?
答案1
|
是管道运算符,它将第一个命令的输出传递给后面的命令。
从man bash
:
管道是由字符 | 分隔的一个或多个命令序列。管道的格式为:
[time [-p]] [ ! ] command [ | command2 ... ]
command 的标准输出通过管道连接到 command2 的标准输入。
在您提供的示例中,id
似乎没有对输出执行任何操作,ls
因此它只是返回与单独运行相同的输出id
。
||
是逻辑或运算符,指定如果第一个命令返回false
或失败(非零)时要做什么。
从man bash
:
控制运算符 && 和 || 分别表示 AND 列表和 OR 列表。AND 列表的形式为
command1 && command2
当且仅当 command1 返回退出状态零时,才会执行 command2。
OR 列表的形式为
command1 || command2
当且仅当 command1 返回非零退出状态时,才会执行 command2。AND 和 OR 列表的返回状态是列表中执行的最后一个命令的退出状态。
在您的示例中,ls -la
运行成功,因此id
命令未运行。如果您执行以下操作:
ls -z || id
并尝试将无效选项传递z
给ls
,然后它会失败并且id
命令会运行。
答案2
|
是管道运算符。从这man sh
:
管道是由 | 分隔的一个或多个命令序列。除最后一个命令外,每个命令的标准输出都通过管道 (2) 连接到下一个命令的标准输入。每个命令都作为单独的进程运行;shell 等待最后一个命令终止。管道的值是其最后一个命令的退出状态。
A | B | C
将获取 A 的标准输出(打印到屏幕上的内容)并将其作为标准输入提供给 B,就像您在交互模式下键入的内容一样,然后 B 将其标准输出提供给 C。
history | grep word
history
打印出你所有的 shell 的历史记录,并grep
打印出与模式匹配的行,所以这会在你的 shell 历史记录中找到你使用过的每个条目word
,因为grep
在没有给出文件名作为参数时会读取 STDIN。
history | tail -n10 | head -n5
获取后 10 行的前 5 行history
,因为tail
和head
在没有给出文件名时都读取 STDIN。
另一方面,||
逻辑或运算符与 C 和类似 C 语言中的相同运算符完全相同。同样,从man sh
:
符号 && 和 || 分别表示仅当前面的管道返回零或非零值时才执行后面的列表。列表中可以出现换行符(而不是分号)来分隔命令。
stat filename || echo "no such file or directory"
stat filename && echo "file exists"
如果stat
找不到文件名,它将返回非零的退出状态,如果找到了,它将以 0 成功退出。这是 C 的逆。(stat
无论如何,高度设计的例子都会给出这样的信息。)
这些本质上与明确检查最后一个命令的退出状态相同,但更短:
stat filename
if [ $? -gt 0 ]; then
echo "no such file or directory"
fi
ETC。