Shell基础一
将命令输出赋值给变量
从命令输出中提取信息,并将其赋值给变量。有两种方法可以将命令输出赋值给变量:
- 反引号字符(`)
- $()格式
#!/bin/bashvar1=`date`echo $var1var2=`date +%y%m%d`echo $var2var3=$(date +%y%m%d)echo $var3
重定向输入输出和管道
输出重定向
command > outputfile
命令输出会被保存到指定的文件中,
➜ ~ who > logs/who.txt➜ ~ cat logs/who.txtxinxingegeya console Mar 27 21:54xinxingegeya ttys000 Mar 27 21:54xinxingegeya ttys001 Mar 27 21:54xinxingegeya ttys002 Mar 27 22:16xinxingegeya ttys004 Mar 27 22:33xinxingegeya ttys005 Mar 27 22:43➜ ~ date >> logs/who.txt➜ ~ cat logs/who.txtxinxingegeya console Mar 27 21:54xinxingegeya ttys000 Mar 27 21:54xinxingegeya ttys001 Mar 27 21:54xinxingegeya ttys002 Mar 27 22:16xinxingegeya ttys004 Mar 27 22:33xinxingegeya ttys005 Mar 27 22:432017年 3月27日 星期一 22时48分43秒 CST➜ ~
注意 使用>> 表示追加输出到已有的文件中。
输入重定向
command < inputfile
输入重定向指的是将文件的内容重定向到命令。
➜ ~ wc < logs/who.txt 7 35 264
比如统计文件who.txt的行数,字数,还有字节数。
内联输入重定向
➜ ~ wc << markerheredoc> asdfsadfasfdasdfheredoc> marker 1 1 17➜ ~
marker作为一个标记,当输入marker标记时,表示输入数据完成,执行wc命令。
管道
使用重定向来实现将一个命令的输出作为另一个命令的输入时,可以这样做,
➜ ~ who > logs/test.txt➜ ~ wc < logs/test.txt 6 30 216➜ ~
但有一种更好的方式来完成
➜ ~ who | wc 6 30 216➜ ~
这就是管道的作用,管道将一个命令的输出重定向到另一个命令中:
command1 | comand2
在脚本中重定向输出
Linux有三个特殊的文件描述符会处理脚本的输入和输出。
STDIN:代表shell的标准输入。对终端界面来说,标准输入是键盘。
STDOUT:代表shell的标准输出,在终端界面上,标准输出就是终端显示器。shell的所有输出(包括shell中运行的程序和脚本)会被定向到标准输出中。
STDERR:shell通过特殊的STDERR文件描述符来处理错误消息。shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置。默认情况下,STDERR和STDOUT文件描述符指向同样的地方。
如何重定向错误
➜ ~ ls -al badfile > logs/test01ls: badfile: No such file or directory➜ ~ cat logs/test01➜ ~ ls -al badfile 2> logs/test01➜ ~ cat logs/test01ls: badfile: No such file or directory➜ ~
使用 2> 将命令的错误消息重定向到了文件test01。但 2> 只重定向错误消息,而非正常的数据输出。如下所示,
➜ ~ ls -al IDE badfile 2> logs/test01IDE:total 32drwxr-xr-x 22 xinxingegeya staff 748 3 17 10:42 .drwxr-xr-x+ 86 xinxingegeya staff 2924 3 28 19:13 ..drwxr-xr-x 4 xinxingegeya staff 136 3 18 00:17 rocketmqdrwxr-xr-x@ 6 xinxingegeya staff 204 12 5 19:15 scala-2.12.1drwxr-xr-x 4 xinxingegeya staff 136 4 14 2016 supervisordrwxr-xr-x 7 xinxingegeya staff 238 3 2 2016 zookeeper➜ ~ cat logs/test01ls: badfile: No such file or directory
如何重定向错误消息和正常的数据输出,使用 &> 符号,如下所示,
➜ ~ ls -al IDE badfile &> logs/test01➜ ~ cat logs/test01ls: badfile: No such file or directoryIDE:total 32drwxr-xr-x 22 xinxingegeya staff 748 3 17 10:42 .drwxr-xr-x+ 86 xinxingegeya staff 2924 3 28 19:17 ..drwxr-xr-x 4 xinxingegeya staff 136 6 23 2016 nginxdrwxr-xr-x 14 xinxingegeya staff 476 6 29 2016 redisdrwxr-xr-x@ 22 xinxingegeya staff 748 6 29 2016 redis-3.0.5drwxr-xr-x 4 xinxingegeya staff 136 3 18 00:17 rocketmqdrwxr-xr-x@ 6 xinxingegeya staff 204 12 5 19:15 scala-2.12.1drwxr-xr-x 4 xinxingegeya staff 136 4 14 2016 supervisordrwxr-xr-x 7 xinxingegeya staff 238 3 2 2016 zookeeper➜ ~
在脚本中重定向输出
#!/bin/bash#重定向到 STDERRecho "this is an error" >&2#正常输出到 STDOUTecho "this is an normal output"
在这个脚本中,将文本消息重定向到STDERR文件描述符,但必须在文件描述符的数字之前加一个&。
运行这个脚本文件,echo输出的信息都会打印到控制台,但可以把脚本重定向到STDERR的输出信息重定向到文件中,而正常的文件输出则还会打印到控制台
➜ resources git:(master) ✗ ./test01.sh 2> hello this is an normal output
如果脚本中有大量的数据需要重定向,那重定向每个echo语句就会很繁琐,那么就可以使用exec命令告诉shell脚本执行期间重定向某个特定文件描述符
#!/bin/bash#重定向 STDOUT 到文件 testoutexec 1>testout#重定向 STDERR 到文件 testout_errexec 2>testout_err#重定向到 STDERRecho "this is an error" >&2#正常输出到 STDOUTecho "this is an normal output"
执行结果如下,
➜ resources git:(master) ✗ ./test01.sh ➜ resources git:(master) ✗ ll total 24-rwxr--r-- 1 xinxingegeya staff 152B Mar 29 18:54 test01.sh-rw-r--r-- 1 xinxingegeya staff 25B Mar 29 18:54 testout-rw-r--r-- 1 xinxingegeya staff 17B Mar 29 18:54 testout_err➜ resources git:(master) ✗ cat testoutthis is an normal output➜ resources git:(master) ✗ cat test_errcat: test_err: No such file or directory➜ resources git:(master) ✗
重定向输出的更多用法
从上文我们知道 &> 的作用是合并STDOUT和STDERR的输出,还有一种写法和 &> 作用一样,
➜ ~ ls -al IDE badfile > my.out0ls: badfile: No such file or directory➜ ~➜ ~ ls -al IDE badfile &> my.out2➜ ~➜ ~ ls -al IDE badfile >& my.out3➜ ~➜ ~ ls -al IDE badfile > my.out4 2>&1➜ ~
(1)ls -al IDE badfile > my.out0
只重定向了正常的数据输出
(2)ls -al IDE badfile &> my.out2
使用 &> 符号重定向错误消息和正常的数据输出
(3)ls -al IDE badfile >& my.out3
>& 符号和 &> 是等价的,作用一样
(4)ls -al IDE badfile > my.out4 2>&1
> my.out4 2>&1 和 (2)(3)的效果是一样的;也就是说先将ls -al IDE badfile 命令的STDOUT输出重定向到文件 my.out4 ,然后再将STDERR重定向到STDOUT,由于前一个重定向把STDOUT重定向的文件,所以STDERR的输出也最终被重定向到了文件。
注意:2>&1代表将stderr重定向到文件描述符为1的文件(即/dev/stdout)中
➜ ~ ls -al IDE badfile 2>&1 > my.out5ls: badfile: No such file or directory➜ ~
这种写法 ls -al IDE badfile 2>&1 > my.out5 和 ls -al IDE badfile > my.out4 2>&1 这种写法只是顺序的不同,但作用是不一样的,为什么呢?先将要输出到stderr的内容重定向到stdout,此时会产生一个stdout的拷贝,作为程序的stderr,而程序原本要输出到stdout的内容,依然是对接在stdout原身上的,因此第二步重定向stdout,对stdout的拷贝不产生任何影响。
http://www.gnu.org/software/bash/manual/bashref.html#Redirections
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1 directs both standard output (file descriptor 1) and
standard error (file descriptor 2) to the file dirlist, while the
command ls 2>&1 > dirlist directs only the standard output to file dirlist,
because the standard error was made a copy of the standard output
before the standard output was redirected to dirlist.
执行数学运算
在shell脚本中使用expr命令,
#!/bin/bashvar1=1var2=2var3=3# 操作数和操作符之间必须有空格var4=$(expr $var1 + $var2 + $var3)echo $var4
使用方括号来执行数学运算。bash shell为了保持和Bourne shell 的兼容而包含了expr命令。在bash中,再将一个数学元算结果赋给某个变量时,可以用美元符号和方括号 $[ operation ] 将数学表达式包围起来。
#!/bin/bashvar1=12var2=23var3=$[$var1 + $var2]echo $var3
在脚本中执行浮点运算
有几种解决方案能够克服bash中数学运算的整数限制。最常见的方案是用内建的bash计算器,叫做bc。
➜ ~ bcbc 1.06Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.This is free software with ABSOLUTELY NO WARRANTY.For details type `warranty'.12 / 52scale=212 / 52.40
首先要设置 scale 的值,默认是0;
在脚本中使用bc,基本命令格式如下,
variable=$(echo "options; expression" | bc)
第一部分options允许你设置变量。如果不止一个变量,可以用分号将其分开。expression参数定义了通过bc执行的数学表达式。
#!/bin/bashvar1=$(echo "scale=2; 12 / 5" | bc)echo $var1
bc 使用内联输入重定向
#!/bin/bashvar1=12.1var2=12.2var3=12.3var4=12.4var5=$(bc << EOFscale = 2a1 = $var1 + $var2b1 = $var3 * $var4a1 + b1EOF)echo $var5
脚本的退出
shell 中运行的每个命令都使用退出状态码(exit status)告诉shell 它已经运行完毕。退出状态码是一个0 ~ 255 的整数值,在命令结束运行时由命令传给shell。可以使用 $? 来获取上个已执行命令的退出状态码。
➜ ~ vim /etc/hosts➜ ~ echo $?0➜ ~ ./hellozsh: no such file or directory: ./hello➜ ~ echo $?127
0 表示 正常退出,127 表示没有找到命令。
默认情况下,shell脚本会以脚本中最后一个命令的退出状态码退出,同时可以使用exit 命令指定一个退出状态码
#!/bin/bashtoday=$(date +%y%m%d)echo $todayexit 0
========END========