设为首页 加入收藏

TOP

Shell 标准输入和输出(一)
2023-07-25 21:38:01 】 浏览:59
Tags:Shell

无论是要交给程序处理的数据,还是控制脚本的简单命令,都少不了输入和输出。程序要做的第一件事就是处理如同一阴一阳的“输入与输出”。

1 、从文件获取输入

当我们希望向文件输出内容时,我们可以通过符号 > 或 >> 实现。而用代表输入重定向的符号 < 可以从文件中读取数据,如下:

$ wc < my.file

之所以选择这种形状的操作符号,原因在于它们可以从视觉上提示重定向的方向。

很多 shell 命令可以接受一个或多个文件名作为参数,但如果没有给出文件名,命令就会从标准输入读取。使用这种命令时,可以采用command filename 或者 command < filename,这两种形式的结果没什么区别。在这个例子中,wc 是这样,换作 cat 或其他命令,也是如此。

2、将数据与脚本存放在一起

< 可以从文件读取数据,当你需要获得脚本输入,但又不想用单独的文件时,使用 <<(here-document)从命令行而非文件重定向输入文本。如果放在 shell 脚本中,则脚本文件可以同时包含数据与代码。

以下是名为 ext.sh 的 shell 脚本示例:

# 下面是here-document
grep $1 <<EOF

mike x.123

joe x.234

sue x.555

pete x.818

sara x.822

bill x.919

EOF

当我们运行此脚本,可以传入一个参数,如下调用:

$ ./ext.sh bill
# 输出以下内容
bill x.919

grep 命令查找第一个参数是否在指定文件中出现,如果没有指定文件,那么它会在标准输入中查找。通过设置 here document,告诉 shell 将标准输入重定向(临时)到此处。<< 语法表示我们想创建一个临时输入源,EOF 是一个任意的字符串(你想用什么都行),用作临时输入的终止符。它并不属于输入的一部分,只是作为标记告诉输入在哪里结束。

3、避免here-document中的怪异行为

here-document 在使用时可能会出现一些怪异的行为。你想用上一节介绍的方法来保存一份简单的捐赠人列表,因此创建了一个名为donors.sh 的文件,如下所示:

# 简单地查找慷慨的捐赠人

grep $1 <<EOF

pete $100

joe $200

sam $ 25

bill $ 9

EOF

但是运行时出现了奇怪的输出:

$ ./donors.sh bill

pete bill00

bill $ 9

$ ./donors.sh pete

pete pete00

正常情况下(除非使用了转义语法),bash 手册页中是这样说的:“……here-document 的每一行都要执行参数扩展、命令替换以及算术扩展”。因此,最初的 donors 脚本中所发生的事情是捐赠额被当作 shell 变量了。例如,$100 被视为 shell 变量 $1,随后跟着两个 0。这就是为什么我们在搜索“pete”时,得到的是 pete00;搜索“bill”时,得到的是 bill00。

解决办法:

通过转义结尾标记中的任意或所有字符,修改脚本内容,关闭 here-document 内部的 shell 特性(注意观察EOF位置的变化):

# 简单地查找慷慨的捐赠人
grep $1 <<'EOF'

pete $100

joe $200

sam $ 25

bill $ 9

EOF

尽管其中存在非常微妙的区别,但也可以将 <<EOF 替换成 <<\EOF或 <<'EOF',甚至是 <<E\OF,都没问题。尽管这并不是最优雅的语法,但足以告诉 bash 你希望区别处理 here-document 中的内容。如果我们转义了 EOF 的部分或全部字符,那么 bash 就知道不用执行扩展,这样就符合我们的预期行为了。

$ ./donors.sh pete

pete $100

4、获取用户输入

输入不止从文件中获取,有时我们还需要获取用户输入的内容。此时,我们需要用到read命令,如下:

$ read

或者

$ read -p "answer me this " ANSWER

不带参数的 read 语句会读取用户输入并将其保存在 shell 变量REPLY 中,这是 read 的最简形式。如果希望 bash 在读取用户输入前先输出提示信息,可以使用 -p 选项。-p 之后的单词就是提示信息,如果想提供多个单词,可以将其引用起来。记住,要在提示信息结尾处加上标点符号或空格,因为光标会停在那里等待输入。-t 选项可以设置超时值。指定秒数达到后,不管用户是否输入,read 语句都会返回。我们的示例同时用到了 -t 和 -p 选项,但你也可以单独使用 -t 选项。

上面的方式获取用户输入时会以明文回显,那适用密码输入么?

当我们需要用户输入敏感信息时,需要禁止用户输入内容的回显。此时用 read 命令读取用户输入,需要加上一个特殊选项来关闭回显:

read -s -p "password: " PASSWD

printf "%b" "\n"

-s 选项告诉 read 命令不要回显输入的字符(s 代表 silent),-p 选项指明下一个参数是提示信息,会在读取用户输入之前显示。从用户那里读取到的输入行保存在变量 $PASSWD 中。在 read 之后,我们用 printf 输出了一个换行符。这里的printf 不能少,因为 read -s 会关闭字符回显。如果禁止了回显功能,当用户按下回车键时,就不会回显换行符,后续输出就会和提示信息出现在同一行。输出换行符会将光标带到下一行。

当然,我们也可以选择一行,如下:

read -s -p "password: " PASSWD ; printf "%b" "\n"

Shell标准输出

如果无法产生输出,那么软件也就没什么价值了,但长久以来,I/O一直是难缠的计算领域之一。问题是有太多类型的输出,向屏幕写入不同于向文件写入,向文件写入也不同于向磁带或闪存写入。所以,对于输出会产生一些问题,如下:

  • 软件开发人员是否要针对各种输出设备编写代码,甚至包括尚未发明的设备?
  • 写到哪个文件?程序怎么知道是该写入代表终端窗口的文件、磁盘文件还是其他种类的文件?

显然,如果把这些事情都交给每个程序员是不合理的,所以这种事情留给shell 就行了。

1、输出到终端/终端窗口

想要用 shell 命令产生一些简单的输出,使用内建命令 echo。命令行中的所有参数都会打印到屏幕上。

echo Please wait.

输出:

Please wait.

结果和在 bash 提示符(字符 $)后输入该命令相同:

file

echo 是最简单的 bash 命令之一。该命令可以将参数输出到屏幕上。但是有几点需要记住:

  • 首先,shell 负责解析 echo 的命令行参数。将参数交给 echo前,shell 会完成所有的替换、通配符匹配等操作。
  • 其次,在解析参数时,参数之间的空白字符会被忽略,如下图:

file

shell 对参数间的空白字符没有太多限制,这通常是一种不错的特性。但对于 echo 来说,就有点烦人了。

  • 保留输出中的空白字符。将字符放入引号中就可以保留空白字符,如下图:
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java Mybatis 笔记 下一篇自从用了 EasyExcel,导入导出 Ex..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目