shell学习笔记(三)shell输入与输出

  1. 云栖社区>
  2. 博客>
  3. 正文

shell学习笔记(三)shell输入与输出

技术小胖子 2017-11-16 04:21:00 浏览822
展开阅读全文

shell学习笔记(三)shell输入与输出目录:

======================================================
echo
read
cat
管道 |
tee
标准输入.输出和错误
文件重定向
    标准输入的重定向
    标准输出的重定向 
    标准输出的重定向 
    标准输出和标准错误的重定向
    标准输入和标准输出的重定向
exec
管道|(pipe)与文件重定向区别

=====================================================

echo
 
显示文本行或变量,或者把字符串输入到文件
 
echo [option] string
-e 解析转义字符
-n 回车不换行,系统默认是回车换行,如:echo 空白
-转义符
\a 发出报警声
\c 回车不换行
\f换行但光标仍旧停留在原来的位置
\t跳格 相对于tab键
\n回车换行
\b 退格键
\r 回车键)
 
eg:
[root@viong_app1 soft]# cat echo
#!/bin/bash
#echo
echo -e "i an lin\c"       不换行
echo -e "i an man\n\n"   回车换行
echo "YES"
echo -e "a\tb\tc\nd\te\bf" 因为e\b 是退格 所以e被删除
echo
echo "wo men\n"
echo -e "i an wei\f"
echo "viong">echo.txt
echo -n "yi qi"
[root@viong_app1 soft]# ./echo
i an lini an man
 
YES
a       b       c
d       f
 
wo men\n
i an wei
 
yi qi[root@viong_app1 soft]# cat echo.txt
viong
[root@viong_app1 soft]#
 
read
 
作用

从标准输入中读取一行。
 
语法

read [ -p ][ -r ][ -s ][ -u[ n ] ] [ VariableName?Prompt ]
[ VariableName ... ]
 
描述
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量,用 IFS(内部字段分隔符)变量中的字符作为分隔符。VariableName 参数指定 shell 变量的名称,shell 变量获取输入行一个字段的值。
由VariableName 参数指定的第一个 shell 变量指定给每一个字段的值,由 VariableName 参数指定的第二个 shell 变量指定给第二个字段的值,以此类推,直到最后一个字段。如果标准输入行的字段比相应的由 VariableName 参数指定的 shell 变量的个数多,把全部余下的字段的值赋给指定的最后的 shell 变量如果比 shell 变量的个数少,则剩余的 shell 变量被设置为空字符串。

注意: 如果省略了 VariableName 参数,变量 REPLY 用作缺省变量名。
由 read 命令设置的 shell 变量影响当前 shell 执行环境
 
以下根据不同参数进行讲解
 
read命令-p(提示语句) -n(字符个数) -t(等待时间) -s(不回显) 和“读文件”
 
#!/bin/bash 
echo -n "Enter your name:"   # -n
阻止换行
read  name                
echo "hello $name "    
exit 0 
 
-------------------------------------------------------------------
[root@viong_app1 soft]# cat read.sh
#!/bin/bash
read -p "Enter your name:" name name1               
echo "hello $name "   
echo "hello $name1 "
exit 0
[root@viong_app1 soft]# ./read.sh
Enter your name:li ming bai
hello li
hello ming bai   #余下的字段的值赋给指定的最后的 shell 变量
 
[root@viong_app1 soft]# ./read.sh
Enter your name:li
hello li
hello   #剩余的 shell 变量被设置为空字符串
 
-p选项允许在read命令行中直接指定一个提示
 
#!/bin/bash 
read –p "Enter your name:" name                  
echo "hello $name "    
exit 0 
 
 
-t选项指定read命令等待输入的秒数。当计时满时,read命令返回一个非零退出状态; 

#!/bin/bash 
if read -t 5 -p "please enter your name:" name 
then 
    echo "hello $name " 
else 
    echo "sorry,time out " 
fi 
exit 0
 
 -n选项后接数值1,指示read命令只要接受到一个字符就退出,只要按下一个字符进行回答,read命令立即接受输入并将其传给变量,无需按回车键.对于read命令来说,-n选项不会检测enter(新行)键
 
#!/bin/bash 
read -n1 -p "Do you want to continue [Y/N]?" answer 
case $answer in 
Y | y) 
      echo "fine ,continue";; 
N | n) 
      echo "ok,good bye";; 
*) 
     echo "error choice";; 
esac 
exit 0 
 
-s选项能够使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是read命令将文本颜色设置成与背景相同的颜色)。 

#!/bin/bash 
read  -s  -p "Enter your password:" pass 
echo "your password is $pass" 
exit 0 
-------------------------------------------------------------------------------------------------
每次调用read命令都会读取文件中的"一行"文本。当文件没有可读的行时,read命令将以非零状态退出,读取文件的关键是如何将文本中的数据传送给read命令 

最常用的方法是对文件使用cat命令并通过管道将结果直接传送给包含read命令的while命令
eg:
[root@viong_app1 soft]# cat test
lin 80
hom 90
viong 100
wang 60
li 70
cheng 50
fan 40
shi 30
-----------------------------------------------------------------------------------------
[root@viong_app1 soft]# cat read.sh
#!/bin/bash
count=1
cat test|while read line     #cat 命令的输出作为read命令的输入,read读到的值放在line
do
   echo "Line $count:$line"
   count=$[ $count + 1 ]    #注意中括号中的空格。
done
echo "finish"
exit 0
 
也可直接
 
#!/bin/bash
count=1
while read line     #cat 命令的输出作为read命令的输入,read读到的值放在line中
do
   echo "Line $count:$line"
   count=$[ $count + 1 ]    #注意中括号中的空格。
done<test          #test为文本文件
echo "finish"
exit 0
 
-------------------------------------------------------------------------------------------
[root@viong_app1 soft]# ./read.sh
Line 1:lin 80
Line 2:hom 90
Line 3:viong 100
Line 4:wang 60
Line 5:li 70
Line 6:cheng 50
Line 7:fan 40
Line 8:shi 30
finish
 
cat
 
说明:把档案串连接后传到基本输出,用它来显示文件内容.创建文件,还可以用它来显示控制字符
 
参数:

-n 或 --number 由 1 开始对所有输出的行数编号 
-b 或 --number-nonblank 和 -n 相似,只不过对于空白行不编号 
-s 或 --squeeze-blank 当遇到有连续两行以上的空白行,就代换为一行的空白行 
-v 或 --show-nonprinting

范例: 
cat -n textfile1 > textfile2 把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里 
cat -b textfile1 textfile2 >> textfile3 把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3 里

范例: 
把 textfile1 的档案内容加上行号后输入 textfile2 这个档案里 
cat -n textfile1 > textfile2 
把 textfile1 和 textfile2 的档案内容加上行号(空白行不加)之后将内容附加到 textfile3 里。 
cat -b textfile1 textfile2 >> textfile3 
cat /dev/null > /etc/test.txt 此为清空/etc/test.txt档案内容
 
管道 |
 
管道是把一个命令的输出传递给另外一个命令作为输入,管道用竖杠“|“表示
 
格式: 命令1|命令2
eg:
cat file|more 分页显示
ll |grep “file”
df -k|awk '{print$1}'|grep -v "文件系统"    命令之间传递
eg:
[root@viong_app1 soft]# df -k
文件系统               1K-        已用     可用 已用% 挂载点
/dev/mapper/VolGroup00-LogVol00
                      18187836   1737764 15511272 11% /
/dev/sda1               101086     12753     83114 14% /boot
tmpfs                   513304         0    513304   0% /dev/shm
 
[root@viong_app1 soft]# df -k|awk '{print$1}'|grep -v "文件系统"
/dev/mapper/VolGroup00-LogVol00
18187836
/dev/sda1
tmpfs
 
tee
 
tee是把输出的一个副本输送到标准输出,另外一个副本拷贝到相应的文件中
 
tee –a files
如果希望在看到输出的同时,也将其存入一个文件,加-a代表累加原有的内容,不覆盖
 
一般用于管道之后
eg: 
[root@viong_app1 soft]# df -k|awk '{print$1}'|grep -v "文件系统" |tee disk
/dev/mapper/VolGroup00-LogVol00
18187836
/dev/sda1
tmpfs
[root@viong_app1 soft]# cat disk
/dev/mapper/VolGroup00-LogVol00
18187836
/dev/sda1
tmpfs
-------------------------------------------------------------------------------------------------
[root@viong_app1 soft]# df -k|awk '{print$1}'|grep -v "文件系统" |tee -a disk
[root@viong_app1 soft]# cat disk
/dev/mapper/VolGroup00-LogVol00
18187836
/dev/sda1
tmpfs
/dev/mapper/VolGroup00-LogVol00
18187836
/dev/sda1
tmpfs
  
标准输入.输出和错误
 
linux启动后,会默认打开3个文件描述符,分别是:标准输入standard input 0,正确输出standard output 1,错误输出:error output 2
 
linux文件描述符:可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作。 用户可以自定义文件描述符范围是:3-num,这个最大数字,跟用户的:ulimit –n 定义数字有关系,不能超过最大值。
关于修改linux文件描述符,请见以下链接
 
以后打开文件后。新增文件绑定描述符 可以依次增加。 一条shell命令执行,都会继承父进程的文件描述符。因此,所有运行的shell命令,都会有默认3个文件描述符
 
文件                              文件描述符
输入文件—标准输入                0(缺省是键盘,也可以是文件或其他命令的输出)
输出文件---标准输出                1(缺省是屏幕,也可以是文件)
错误输出文件—标准错误            2(缺省是屏幕,也可以是文件)
 
系统中实际上有12个文件描述符,可以任意使用文件描述符3到9
 
文件重定向
 
所谓文件重定向就是改变程序运行的输入来源和输出地点
 
标准输入的重定向
 
命令默认从键盘获得的输入,改成从文件,或者其它打开文件以及设备输入,执行这个命令,将标准输入0,与文件或设备绑定,将由它进行输入.
 
command < filename             command命令以filename文件作为标准输入
command << delimiter(定界符)  从标准输入中读入,直到遇到delimiter定界符
command < &m                 把文件描述符m作为标准输入
eg:
[root@viong_app1 soft]# cat name
2
3
5
6
9
1
4
[root@viong_app1 soft]# sort < name
1
2
3
4
5
6
9
---------------------------------------------------------------------------
 
[root@viong_app1 soft]# cat score
beyes 10000 90 78 98
admin 10001 99 64 72
tony 10002 45 32 56
tom   10003 12 34 87
lilei 10004 48 25 70
 
[root@viong_app1 soft]# cat >> score <<exit
> viong 10005 49 30 80
> exit
[root@viong_app1 soft]# cat score
beyes 10000 90 78 98
admin 10001 99 64 72
tony 10002 45 32 56
tom   10003 12 34 87
lilei 10004 48 25 70
viong 10005 49 30 80
--------------------------------------------------------------------------
以上cat>>score<<exit 命令解释:
cat>>score
输入viong 10005 49 30 80
这里按下ctrl+d或者ctrl+c离开
从标准输入【键盘】获得数据,然后输出追加给score文件
 
[root@lvs_app1 soft]# cat score
beyes 10000 90 78 98
admin 10001 99 64 72
tony 10002 45 32 56
tom   10003 12 34 87
lilei 10004 48 25 70
viong 10005 49 30 80
viong 10005 49 30 80
 
<<exit 直到遇到exit定界符,退出,相当于结束的输入字符,不用按ctrl+d或者ctrl+c离开
-------------------------------------------------------------------------------------
[root@lvs_app1 soft]# cat score1
cao   10005 22 38 80
[root@lvs_app1 soft]# cat>>score<score1   #cat从score1获得输入数据,然后输出追加给score文件
[root@lvs_app1 soft]# cat score
beyes 10000 90 78 98
admin 10001 99 64 72
tony 10002 45 32 56
tom   10003 12 34 87
lilei 10004 48 25 70
viong 10005 49 30 80
viong 10005 49 30 80
cao   10005 22 38 80
 
标准输出的重定向  
 
将一条命令执行结果(标准输出,本来都要打印到屏幕上面的) 重定向其它输出设备(文件,打开文件操作符,或打印机等等)
 
command > filename     把标准输出重定向到一个新文件
command 1 > filename    同上
command >> filename    把标准输出重定向到一个文件中(追加)
command > &m         把标准输出重定向到文件描述符m中
command 1>&-          关闭标准输出
eg:
 
[root@viong_app1 viong]# ll >test
[root@viong_app1 viong]# cat test
总计 12
-rw-r--r-- 1 root root    0 05-29 16:52 test
drwxr-xr-x 2 root root 4096 04-22 21:44 viong
 
[root@viong_app1 viong]# ll 1>test
[root@viong_app1 viong]# cat test
总计 12
-rw-r--r-- 1 root root    0 05-29 16:52 test
drwxr-xr-x 2 root root 4096 04-22 21:44 viong
-------------------------------------------------------------
[root@viong_app1 viong]# ll >>test
[root@viong_app1 viong]# cat test
总计 12
-rw-r--r-- 1 root root    0 05-29 16:52 test
drwxr-xr-x 2 root root 4096 04-22 21:44 viong
总计 16
-rw-r--r-- 1 root root 101 05-29 16:52 test
drwxr-xr-x 2 root root 4096 04-22 21:44 viong
 
shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空
 
eg:
[root@viong_app1 soft]# >test   #test文件存在,就清空内容,不存在就创建一个空文件test
 
标准错误的重定向
 
command 2 > filename   把标准错误重定向到一个新文件
command >> filename    把标准错误重定向到一个文件中(追加)
command 2>&-          关闭标准错误
eg:
 
[root@viong_app1 soft]# ll hom hom1 2>err.txt
-rw-r--r-- 1 root root 101 05-09 18:45 hom
 
[root@viong_app1 soft]# cat err.txt
ls: hom1: 没有那个文件或目录
 
[root@viong_app1 soft]# ll hom hom1 2>>err.txt
-rw-r--r-- 1 root root 101 05-09 18:45 hom
 
[root@viong_app1 soft]# cat err.txt
ls: hom1: 没有那个文件或目录
ls: hom1: 没有那个文件或目录
 
--------------------------------------------------------------------------------------------------
[root@viong_app1 soft]# ll hom hom1 2>/dev/null
-rw-r--r-- 1 root root 101 05-09 18:45 hom
 
[root@lvs_app1 soft]# ll hom hom1 1>/dev/null 2>/dev/null     #把标准输出和错误转发给/dev/null
 
[root@lvs_app1 soft]# ll hom hom1 &>/dev/null   #把标准输出和错误转发给/dev/null
 
-------------------------------------------------------------------------------------------------
[root@lvs_app1 soft]# ll hom hom1 2>&-         #关闭标准错误
-rw-r--r-- 1 root root 101 05-09 18:45 hom
 
[root@lvs_app1 soft]# ll hom hom1 1>&- 2>&-      #关闭标准输出和错误
 
[root@lvs_app1 soft]# ll hom hom1 &>-          #关闭标准输出和错误
 
标准输出和标准错误的重定向
 
合并标准输出和标准错误的时候,切记shell是从做到右分析相应的命令
 
command > filename 2>&1 把标准输出和标准错误一起重定向到一个文件中
 
命令解释:首先command命令标准输出到filename文件,如遇到标准错误输出到&1.而&1代表缺省屏幕(标准输出),而缺省屏幕输出到filename文件,及所有错误和结果输出到filename文件中
 
command >> filename 2>&1 把标准输出和标准错误一起重定向到一个文件中(追加)
 
eg: 
[root@viong_app1 soft]# >err.txt                 #先清空err.txt文件内容
[root@viong_app1 soft]# ll hom hom1>err.txt 2>&1 #标准输出和错误都重定向到err.txt文件中
 
[root@viong_app1 soft]# cat err.txt
ls: hom1: 没有那个文件或目录
-rw-r--r-- 1 root root 101 05-09 18:45 hom
 
[root@viong_app1 soft]# ll hom hom1>>err.txt 2>&1
 
[root@viong_app1 soft]# cat err.txt
ls: hom1: 没有那个文件或目录
-rw-r--r-- 1 root root 101 05-09 18:45 hom
ls: hom1: 没有那个文件或目录
-rw-r--r-- 1 root root 101 05-09 18:45 hom
-------------------------------------------------------------------------------------------------
[root@viong_app1 soft]# > err.txt
[root@viong_app1 soft]# ll hom hom1 2>err.txt 1>homnew  #标准输出和错误分别重定向到不同文件中
[root@viong_app1 soft]# cat err.txt
ls: hom1: 没有那个文件或目录
[root@viong_app1 soft]# cat homnew
-rw-r--r-- 1 root root 101 05-09 18:45 hom
 
标准输入和标准输出的重定向
 
command < filename <filename 2   command命令以filename文件作为标准输入,以fi lename2文件作为标准输出
eg:
 
[root@viong_app1 soft]# cat name
2
3
5
6
9
1
4
[root@viong_app1 soft]# sort <name >name1类似cat name|sort>name1命令
[root@viong_app1 soft]# cat name1
1
2
3
4
5
6
9
 
exec
 
格式:
 
exec 文件描述符[n] <或> file或文件描述符或设备
 
在上面讲的输入,输出重定向 将输入,输出绑定文件或设备后,只对当前那条指令是有效的,如果需要在绑定之后,接下来的所有命令都支持的话,就需要用exec命令
 
exec命令可以用来替代当前shell,换句话说,并没有启动子shell,使用这一命令时任何现有环境变量将会被清除,并重新启动一个shell
 
exec command
 
其中command通常是一个shell脚本
 
对文件描述符进行操作的时候,它不会覆盖当前的shell
eg:
 
[root@viong_app1 soft]# export viong=10
[root@viong_app1 soft]# echo $viong
10
[root@viong_app1 soft]# exec ./hello.sh
#这个时候退出当前shell,重新启动一个shell
[root@viong_app1 ~]# echo $viong   #查看之前环境变量已被清除
 
[root@viong_app1 ~]#
--------------------------------------------------------------------------------------------------
[root@lvs_app1 soft]# exec 5<&1   #将标准输出与文件描述符5绑定
 
 
[root@lvs_app1 soft]# ls /proc/self/fd #出现文件描述符5
0         1 2 3 5
 
[root@lvs_app1 soft]# exec 1>exec.txt #接下来所有命令标准输出,绑定到exec.txt文件(输出到该文件)注意:这里输出的内容是追加的
 
[root@lvs_app1 soft]# ll             #执行命令后并无返回结果
 
[root@lvs_app1 soft]# exec 1<&5     #恢复标准输出
[root@lvs_app1 soft]# ll             #执行命令后返回结果到屏幕上
 
总计 484
-rwxr-xr-x 1 root root   339 05-16 16:07 break.sh
-rwxr-xr-x 1 root root   269 05-16 17:01 case.sh
-rwxr-xr-x 1 root root   702 05-16 16:17 continue.sh
………………………..
[root@lvs_app1 soft]# exec 5>&-      #关闭文件描述符5
[root@lvs_app1 soft]# ls /proc/self/fd
0 1 2 3
 
--------------------------------------------------------------------------------------------------
[root@viong_app1 soft]# cat name
2
3
5
6
9
1
4
 
[root@viong_app1 soft]# cat exec.sh
#!/bin/bash
#exec_test
exec 3<&0 0<name
read line1
read line2
exec 1<&3
echo $line1
echo $line2
 
[root@viong_app1 soft]# ./exec.sh
2
3
[root@lvs_app1 soft]# cat exec.sh
#!/bin/bash
#exec_test
exec 3<>name           #打开name可读性操作,与文件描述符3绑定
while read line<&3
do
echo $line
done
exec 3>&-
exec 3<&-
 
[root@lvs_app1 soft]# ./exec.sh
2
3
5
6
9
1
4
------------------------------------------------------------------------------------------------------
[root@lvs_app1 soft]# exec 6<&1
[root@lvs_app1 soft]# ls /proc/self/fd/
0 1 2 3 6
[root@lvs_app1 soft]# exec 6<&1-
-bash: echo: write error: 错误的文件描述符
-bash: echo: write error: 错误的文件描述符
[root@lvs_app1 soft]# exec 6<&-
-bash: echo: write error: 错误的文件描述符
-bash: echo: write error: 错误的文件描述符
 
遇到以上因为疏误导致无法输入任何命令,就要利用之前重启shell命令
[root@viong_app1 soft]# exec ./hello.sh   #重启到另外一个shell
 
[root@lvs_app1 ~]# ls /proc/self/fd/     #恢复正常状态
0         1 2 3
 
管道|(pipe)与文件重定向区别
1、管道命令只处理前一个命令正确输出,不处理错误输出
2、管道命令右边命令,必须能够接收标准输入流命令才行。
接收标准输入的命令才可以用作管道右边。否则传递过程中数据会抛弃。 常用来作为接收数据管道命令有:sed,awk,cut,head,top,less,more,wc,join,sort,split 等等,都是些文本处理命令。
 

    本文转自viong 51CTO博客,原文链接:http://blog.51cto.com/viong/894428,如需转载请自行联系原作者



网友评论

登录后评论
0/500
评论