编程工具(三)Shell编程基础
参考:《Shell从入门到精通》 参考:Shell 编程快速入门 参考:Shell 教程 参考:Shell编程入门总结(一) 一、ShellShell脚本(英语:Shell script)是一种电脑程序与文本文件,内容由一连串的shell命令组成,由Unix shell扮演命令行解释器的角色,经由Unix Shell直译其内容后运作。 Shell的用处:
Shell不适用的场合:
二、Shell环境
shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。当前主流的操作系统都支持shell编程。
Linux Linux默认安装就带了shell解释器。 Mac OS Mac OS不仅带了sh、bash这两个最基础的解释器,还内置了ksh、csh、zsh等不常用的解释器。 Windows上的模拟器 windows出厂时没有内置shell解释器,需要自行安装,为了同时能用grep,awk,curl等工具,最好装一个cygwin或者mingw来模拟linux环境。
sh
即Bourne shell,POSIX(Portable Operating System Interface)标准的shell解释器,它的二进制文件路径通常是/bin/sh,由Bell Labs开发。 bash Bash是Bourne shell的替代品,属GNU Project,二进制文件路径通常是/bin/bash。在CentOS里,/bin/sh是一个指向/bin/bash的符号链接,但在Mac OS上不是,/bin/sh和/bin/bash是两个不同的文件,尽管它们的大小只相差100字节左右,业界通常混用bash、sh、和shell。 三、Shell的解释和执行
Shell的格式
通常shell脚本以.sh为后缀。在编写shell时,第一行一定要指明系统需要哪种shell解释用户的shell程序,如:
Shell的执行
通常,shell脚本会以#!/bin/sh作为默认的shell程序。执行shell的方式有两种:
第一种是为shell脚本加上可执行权限并执行;
第二种是通过sh命令执行shell脚本,例如执行当前目录下的run.sh脚本,命令如下:
//为shell脚本直接加上可执行权限并执行 chmod 755 run.sh ./run.sh //通过sh命令执行shell脚本 sh run.sh 四、Shell中的特殊字符
和其他编程语言一样,shell里也有特殊字符。常见的有美元符号($),反斜线()和引号。
1. 美元符号 美元符号表示变量替换,即用其后面指定的变量的值来代替变量。反斜线“”为转义字符,转义字符告诉shell不要对其后面的那个字符进行特殊处理,只是当做普通字符。而shell下的引号情况比较复杂,分为三种:双引号("),单引号(')和倒引号(`)。他们的作用都不尽相同,以下一一说明。 2. 双引号(") 由双引号括起来的字符,除$,倒引号(`)和反斜线()仍保留其特殊功能外,其余字符均作为普通字符对待。 3. 单引号(') 由单引号括起来的字符都作为普通字符出现。 4. 倒引号(`) 由倒引号括起来的字符串被shell解释为命令行,在执行时,shell会先执行该命令,并以它的标准输出结果取代整个引号部分。 示例1的代码及输出如下: #echo "My current directory is `pwd` and logname is $LOGNAME"
【双引号中的倒引号和美元符号保持原来的功能】
My current directory is /root and logname is root示例2的代码及输出如下: #echo "My current directory is `pwd` and logname is $LOGNAME"
【双引号中的转义字符保持原来的功能】
My current directory is /root and logname is $LOGNAME示例3的代码及输出如下: #echo 'My current directory is `pwd` and logname is $LOGNAME'【单引号里面的内容不变】 My current directory is `pwd`and logname is $LOGNAME 五、Shell中的变量
1. 创建变量或给变量赋值
variable=value(注:等号左右不能有空格)2.可以在同一行中对多个变量赋值 a=5 b="a string"3.使用变量 $variable 或 ${variable}4.只读变量 myUrl="http://www.w3cschool.cc" readonly myUrl myUrl="http://www.baidu.com"运行脚本,结果如下: /bin/sh: NAME: This variable is read only.5.删除变量 unset variable_name变量被删除后不能再次使用。unset 命令不能删除只读变量。
6. 变量类型
运行shell时,会同时存在三种变量:
1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行 7. 变量的通配符 假设有变量 var=http://www.aaa.com/123.htm 1. # 号截取,从左边开始删除第一个匹配到的字符及左边的字符,保留右边字符。 echo ${var#*//} # 号是运算符,*// 表示 // 号及左边的所有字符,即删除 http:// 结果是 :www.aaa.com/123.htm 2. ## 号截取,从左边开始删除最后一个匹配到的字符及左边的字符,保留右边字符。 ##*/} ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符,即删除 http://www.aaa.com/ 结果是 123.htm 3. %号截取,删除从右开始第一个匹配到的字符及右边字符,保留左边字符 var%/*} %/* 表示从右边开始,删除第一个 / 号及右边的字符 结果是:http://www.aaa.com 4. %% 号截取,删除从右开始最后一个匹配到的字符及右边字符,保留左边字符 %% %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。 6. 从左边第几个字符开始,一直到结束。 7 其中的 7 表示左边第8个字符开始,一直到结束。
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。
1.定义数组
array_name=(value0 value1 value2 value3)用括号来表示数组,数组元素用"空格"符号分割开。还可以单独定义数组的各个分量: array_name[0]=value0 array_name[1]=value1 array_name[n]=valuen2.读取数组 valuen=${array_name[n]}使用@符号可以获取数组中的所有元素 3.获取数组的长度 # 取得数组元素的个数 length=${#array_name[@]} # 或者 length=${#array_name[*]} # 取得数组单个元素的长度 lengthn=${#array_name[n]} 七、Shell中的函数和运算符7.1 函数语法形式function name { commands return }或 name () { commands return }
其中name为函数名,commands为一系列包含在函数中的命令,函数中须至少包含一条命令,return为可选。Shell 提供了一个参数$?可用来检查退出状态,即函数中的返回值(返回值只能是整数)。
我们可以在执行 Shell 脚本或函数时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推。$0 为执行的文件名(在bash中为“bash”)。
7.2 表达式计算工具
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。如下两个数相加(注意使用的是反引号 ` 而不是单引号 '):
#!/bin/bash val=`expr 2 + 2` echo "两数之和为 : $val"表达式和运算符之间要 有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。 7.3 算数运算符
7.4关系运算符
关系运算符只支
持数字,不支持字符串,除非字符串的值是数字。下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:
7.5 布尔运算符
7.6逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20
7.7字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":
7.8文件测试运算符
八、Shell中的逻辑控制语句1. if 语句if commands; then commands elif commands; then commands else commands fi
2. for语句
for var in item1 item2 ... itemN do command1 command2 ... commandN done当变量值在列表里,for循环即 执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的shell命令和语句。in列表可以包含替换、字符串和文件名。in列表是可选的,如果不用它,for循环使用命令行的位置参数。
3. while语句
while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:
while condition do command done
4. util语句
until循环执行一系列命令直至条件为真时停止。until循环与while循环在处理方式上刚好相反。一般while循环优于until循环,但在某些时候—也只是极少数情况下,until循环更加有用。until 语法格式:
until condition do command done条件可为任意测试条件,测试发生在 循环末尾,因此循环 至少执行一次—请注意这一点。
5. case
Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:
case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esaccase工作方式如上所示。取值后面必须为单词 in,每一模式必须以 右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。 九、Shell中的测试语句
经常与 if 一块使用的命令是 test。test 命令执行各种各样的检查与比较,它有两种等价模式:
test expression
或 [ expression ]
其中expression 为一个表达式,其执行结果是 true 或者是 false。当表达式为真时,这个 test 命令返回一个0退出状态,当表达式为假时,test 命令退出状态为1。
正则表达式和[[ expression ]]
目前的 bash 版本包含一个复合命令:[[ expression ]],与test相比增加了一个重要的新的字符串表达式:string1 =~ regex,若string1匹配扩展的正则表达式 regex则返回真
#!/bin/bash # test-integer2: evaluate the value of an integer. INT=-5 if [[ "$INT" =~ ^-?[0-9]+$ ]]; then if [ $INT -eq 0 ]; then echo "INT is zero." else if [ $INT -lt 0 ]; then echo "INT is negative." else echo "INT is positive." fi if [ $((INT % 2)) -eq 0 ]; then echo "INT is even." else echo "INT is odd." fi fi else echo "INT is not an integer." >&2 exit 1 fi 整数复合命令(( ))
"(( ))"是专门为整数运算设计的复合命令,双括号内的运算符号(+、-、*、/、%)和比较符号(>、<)不需要转义即可使用。
#!/bin/bash # test-integer2a: evaluate the value of an integer. INT=-5 if [[ "$INT" =~ ^-?[0-9]+$ ]]; then if ((INT == 0)); then echo "INT is zero." else if ((INT < 0)); then echo "INT is negative." else echo "INT is positive." fi if (( ((INT % 2)) == 0)); then echo "INT is even." else echo "INT is odd." fi fi else echo "INT is not an integer." >&2 exit 1 fi 十、Shell中的输入和交互
read - 从标准输入读取单行数据,read读取一个整数示例如下:
echo -n "Please enter an integer -> " read var echo "var = '$var'"给多个变量赋值: echo -n "Enter one or more values > " read var1 var2 echo "var1 = '$var1'" echo "var2 = '$var2'"若没有提供变量名,shell 变量 REPLY 会包含数据行 echo -n "Enter one or more values > " read echo "REPLY = '$REPLY'"read选项:read [-options] [variable...]
密码输入脚本
此脚本提示用户输入一个密码,若在10秒内没有完成输入,则脚本会退出并返回一个错误。因包含了一个 -s 选项,所以输入的密码不会出现在屏幕上。
#!/bin/bash if read -t 10 -sp "Enter secret pass phrase > " secret_pass; then echo -e "nSecret pass phrase = '$secret_pass'" else echo -e "nInput timed out" >&2 exit 1 fi输入校正
通过对输入的数据进行校验,得到期望范围内的输入
#!/bin/bash invalid_input () { echo "Invalid input '$REPLY'" >&2 exit 1 } read -p "Enter a single item > " # input is empty (invalid) [[ -z $REPLY ]] && invalid_input # input is multiple items (invalid) (( $(echo $REPLY | wc -w) > 1 )) && invalid_input # is input a valid filename? if [[ $REPLY =~ ^[-[:alnum:]._]+$ ]]; then echo "'$REPLY' is a valid filename." if [[ -e $REPLY ]]; then echo "And file '$REPLY' exists." else echo "However,file '$REPLY' does not exist." fi # is input a floating point number? if [[ $REPLY =~ ^-?[[:digit:]]*.[[:digit:]]+$ ]]; then echo "'$REPLY' is a floating point number." else echo "'$REPLY' is not a floating point number." fi # is input an integer? if [[ $REPLY =~ ^-?[[:digit:]]+$ ]]; then echo "'$REPLY' is an integer." else echo "'$REPLY' is not an integer." fi else echo "The string '$REPLY' is not a valid filename." fi菜单驱动
一种常见的交互类型称为菜单驱动,从逻辑上讲,这个脚本被分为两部分。第一部分显示菜单和用户输入。第二部分确认用户反馈,并执行 选择的行动
#!/bin/bash # read-menu: a menu driven system information program clear echo " Please Select: 1. Display System Information 2. Display Disk Space 3. Display Home Space Utilization 0. Quit " read -p "Enter selection [0-3] > " if [[ $REPLY =~ ^[0-3]$ ]]; then if [[ $REPLY == 0 ]]; then echo "Program terminated." exit fi if [[ $REPLY == 1 ]]; then echo "Hostname: $HOSTNAME" uptime exit fi if [[ $REPLY == 2 ]]; then df -h exit fi if [[ $REPLY == 3 ]]; then if [[ $(id -u) -eq 0 ]]; then echo "Home Space Utilization (All Users)" du -sh /home/* else echo "Home Space Utilization ($USER)" du -sh $HOME fi exit fi else echo "Invalid entry." >&2 exit 1 fi
|
command > file | 将输出重定向到 file。 |
---|---|
将输入重定向到 file。 | |
command >> file | 将输出以追加的方式重定向到 file。 |
将文件描述符为 n 的文件重定向到 file。 | |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
将输出文件 m 和 n 合并。 | |
n <& m | 将输入文件 m 和 n 合并。 |
将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
1、shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空。
2、“>>”操作符,判断右边文件,如果不存在,先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1,2]然后,与左边的标准输出(1)或错误输出(2) 绑定。
3、当命令:执行完,绑定文件的描述符也自动失效。0,1,2又会空闲。
4、一条命令启动,命令的输入,正确输出,错误输出,默认分别绑定0,2文件描述符。
5、一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行
3.输入重定向
command-line [n] <file或文件描述符&设备命令将默认从键盘获得的输入,改成从文件,或者其它打开文件以及设备输入。执行这个命令,将标准输入0,与文件或设备绑定。将由它进行输入。
[zenhobby@zencode shell]# cat > catfile testing cat file test #这里按下 [ctrl]+d 离开 #从标准输入【键盘】获得数据,然后输出给catfile文件 [zenhobby@zencode shell]$ cat>catfile <test.sh #cat 从test.sh 获得输入数据,然后输出给文件catfile [zenhobby@zencode shell]$ cat>catfile <<eof test a file test! eof #<< 这个连续两个小符号, 他代表的是『结束的输入字符』的意思。这样当空行输入eof字符,输入自动结束,不用ctrl+D
4.重定向到空设备文件
1>/dev/null 2>&11. 标准输入stdin文件描述符为0,标准输出stdout文件描述符为1,标准错误stderr文件描述符为2
2. /dev/null 空设备文件,相当于垃圾桶
- 0代表标准输入
- 1代表stdout标准输出,默认值为1,所以”1>/dev/null”可以简写为”>/dev/null”
- 2代表stderr标准错误输出
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!