shell命令的标准输入(stdin)
在 shell 命令中,有多种方式可以灵活地控制命令的标准输入(stdin),熟练掌握这些技巧有时会起到事半功倍的效果。
管道符号(|
)
管道操作可以将一个命令的输出重定向到另一个命令的输入:
1 | echo "$string" | command |
这是最方便,也最为广泛使用的一种方式。但这种方式有个缺陷,即管道符之后的命令是在一个子 shell 进程中运行的,它的运行效果无法作用到当前 shell 进程。
考虑以下命令:
1 | echo "hello world" | read first second |
会发现第二条 echo
命令的输出为空,并非预期中的 world hello
(注意,一些特殊的 shell 如 zsh 不存在该问题)。事实上,read
命令确实正确地读取了两个变量,但之后该 shell 子进程结束,控制权回到主进程,变量又被丢弃了。
为了避免这种情况,可以使用花括号把 shell 子进程中的所有命令括起来:
1 | echo "hello world" | { |
这使得第二个 echo
命令能够正常输出 world hello
,但仍然无法把 first
和 second
两个变量带到主进程中来。
here-string(<<<
)
继续上面的例子,除了管道符之外,我们有没有办法把字符串"hello world"
以标准输入的形式传递给 read
命令呢?
有。一个非常方便的办法是使用“here-string”:
1 | read first second <<< "hello world" |
上述命令不仅能够符合预期地输出 world hello
,而且 first
和 second
两个变量也被保存到了当前 shell 中,随时可用。
here-document(<<
)
here-document 可以认为是 here-string 的高阶形式,它支持多行输入,适合输入大段文本。
在 shell 命令行中使用方式如下:
1 | $ cat <<EOF |
注意:其中的 $
表示命令提示符,>
表示换行,均由 shell 提供,并非用户输入。EOF
为标志字符串,代表输入的开头和结尾,可以替换为其他任意字符串。
here-documnet 在 shell 脚本中使用的例子如下:
1 | cat > out.txt <<FILE |
这段脚本会将两个 FILE
之间的那段文本写入 out.txt
文件中。
输入重定向(<
)
输入重定向符号(<
)后需要接一个文件路径,表示将文件的内容重定向到标准输入。例如:
1 | echo "hello world" > tmp.txt |