shell编程
http://www.renren.io/linux/linux_shell.html
简单的shell脚本实例
echo:
ex: echo "hello world"
printf:
ex:
printf "hello world"
printf "%-5s %-10s %-4.2f\n" 03 Tom 90.3456
- %-5s 格式为左对齐且宽度为5的字符串代替(-表示左对齐),不使用则是右对齐。
- %-4.2f 格式为左对齐宽度为4,保留两位小数。
格式替代符
- %b 相对应的参数被视为含有要被处理的转义序列之字符串。
- %c ASCII字符。显示相对应参数的第一个字符
- %d, %i 十进制整数
- %e, %E, %f 浮点格式
- %g %e或%f转换,看哪一个较短,则删除结尾的零
- %G %E或%f转换,看哪一个较短,则删除结尾的零
- %o 不带正负号的八进制值
- %s 字符串
- %u 不带正负号的十进制值
- %x 不带正负号的十六进制值,使用a至f表示10至15
- %X 不带正负号的十六进制值,使用A至F表示10至15
- %% 字面意义的%
转义序列
- \a 警告字符,通常为ASCII的BEL字符
- \b 后退
- \c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
- \f 换页(formfeed)
- \n 换行
- \r 回车(Carriage return)
- \t 水平制表符
- \v 垂直制表符
- \\ 一个字面上的反斜杠字符
- \ddd 表示1到3位数八进制值的字符,仅在格式字符串中有效
- \0ddd 表示1到3位的八进制值字符
在echo中转义换行符
echo -e "包含转义序列的字符串"
echo -e "1\t2\t3" 1 2 3
打印彩色输出
文字色
echo -e "\e[1;31mThis is red text\e[0m" This is red text
- \e[1;31m 将颜色设置为红色
- \e[0m 将颜色重新置回
颜色码:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37
背景色
echo -e "\e[1;42mGreed Background\e[0m" Greed Background
颜色码:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47
文字闪动
echo -e "\033[37;31;5mMySQL Server Stop...\033[39;49;0m"
红色数字处还有其他数字参数:0 关闭所有属性、1 设置高亮度(加粗)、4 下划线、5 闪烁、7 反显、8 消隐
算术运算
整数运算
let运算命令
#!/bin/bash no1=2; no2=3; let result=no1+no2 echo $result
- 自加操作
let no++ - 自减操作
let no-- - 简写形式
let no+=10let no-=20分别等同于let no=no+10let no=no-20
操作符[]运算方法
#!/bin/bash no1=2; no2=3; result=$[$no1+no2] echo $result
使用方法和let相似,在[]中可以使$前缀。
(())运算方法
#!/bin/bash no1=2; no2=3; result=$((no1+no2)) echo $result
expr运算方法
result=`expr 2 + 3` result=$(expr $no1 + 5)
expr的常用运算符
- 加法运算:+
- 减法运算:-
- 乘法运算:\*
- 除法运算:/
- 求摸(取余)运算:%
精密计算
算术操作高级运算工具:bc,它可以执行浮点运算和一些高级函数
echo "1.212*3" | bc 3.636
设定小数精度(数值范围)
echo "scale=2;3/8" | bc 0.37
参数scale=2是将bc输出结果的小数位设置为2位。
进制转换
#!/bin/bash abc=192 echo "obase=2;$abc" | bc
执行结果为:11000000,这是用bc将十进制转换成二进制。
#!/bin/bash abc=11000000 echo "obase=10;ibase=2;$abc" | bc
执行结果为:192,这是用bc将二进制转换为十进制。
计算平方和平方根
echo "10^10" | bc echo "sqrt(100)" | bc
常用变量
结合不同的引号为变量赋值
- 双引号 "" :允许通过$符号引用其他变量值
- 单引号 '' :禁止引用其他变量值,$视为普通字符
- 反撇号 `` :将命令执行的结果输出给变量
用户自定义变量
设置变量的作用范围
格式:
export 变量名...
export 变量名=变量值 [...变量名n=变量值n]
清除用户自定义变量
格式:
unset 变量名
环境变量
环境变量配置文件
- 全局配置文件:/etc/profile
- 用户配置文件:~/.bash_profile
查看环境变量
常见的环境变量
- $USER 查看账户信息
- $logname 登录相关信息
- $UID
- $Shell
- $HOME 家目录
- $pwd
- $PATH 用户所输入的命令是在哪些目录中查找
- $PS1
- $PS2
- $RANDOM 随机数
位置变量
表示为:$n (n为1~9之间的数字)
#./test.sh one two three four five six
- $0 表示文件名本身
- one就是:$1
- two就是:$2
预定义变量
- $# :命令行中位置参数的个数
- $* :所有位置参数的内容
- $? :上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0表示执行异常或出错
- $$ :当前所在进程的进程号
- $! :后台运行的最后一个进程号
- $0 :当前执行的进程/程序名
============================================================================
read命令
read命令从键盘读取变量的值,通常用在shell脚本中与用户进行交互的场合。该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。在read命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量REPLY
语法
read(选项)(参数)
选项
-p:指定读取值时的提示符; -t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名。
实例
下面的列表给出了read命令的常用方式:
read 1987name 从标准输入读取输入并赋值给变量1987name。
read first last
从标准输入读取输入到第一个空格或者回车,将输入的第一个单词放到变量first中,并将该行其他的输入放在变量last中。
read 从标准输入读取一行并赋值给特定变量REPLY。
read -a arrayname 把单词清单读入arrayname的数组里。
read -p "text" 打印提示(text),等待输入,并将输入存储在REPLY中。
read -r line 允许输入包含反斜杠。
read -t 3 指定读取等待时间为3秒。
read -n 2 var 从输入中读取两个字符并存入变量var,不需要按回车读取。
read -d ":" var 用定界符“:”结束输入行。
read命令示例
等待一组输入,每个单词之间使用空格隔开,直到回车结束,并分别将单词依次赋值给这三个读入变量。
#read one two three 1 2 3 #在控制台输入1 2 3,它们之间用空格隔开。 #echo "one = $one, two = $two, three = $three" one = 1, two = 2, three = 3
REPLY示例
#read #等待控制台输入,并将结果赋值给特定内置变量REPLY。 This is REPLY #在控制台输入该行。 #echo $REPLY #打印输出特定内置变量REPLY,以确认是否被正确赋值。 This is REPLY
-p选项示例
#read -p "Enter your name: " #输出文本提示,同时等待输入,并将结果赋值给REPLY。 Enter you name: stephen #在提示文本之后输入stephen #echo $REPLY stephen
等待控制台输入,并将输入信息视为数组,赋值给数组变量friends,输入信息用空格隔开数组的每个元素。
#read -a friends
Tim Tom Helen
#echo "They are ${friends[0]}, ${friends[1]} and ${friends[2]}."
They are Tim, Tom and Helen.
补充一个终端输入密码时候,不让密码显示出来的例子。
方法1:
#!/bin/bash
read -p "输入密码:" -s pwd
echo
echo password read, is "$pwd"
方法2:
#!/bin/bash stty -echo read -p "输入密码:" pwd stty echo echo echo 输入完毕。
其中,选项-echo禁止将输出发送到终端,而选项echo则允许发送输出。
注意:使用echo命令输出变量值时,必须在变量名前添加符号$。否则,echo将直接输出变量名。
==============================================================================
文件的描述符和重定向
文件描述符是和文件的输入、输出相关联的非负整数,Linux内核(kernel)利用文件描述符(file descriptor)来访问文件。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。常见的文件描述符是stdin、stdout和stderr。
系统预留文件描述符
- 0 —— stdin(标准输入)
- 1 —— stdout(标准输出)
- 2 —— stderr(标准错误)
重定向将输入文本通过截取模式保存到文件:
echo "this is a text line one" > test.txt
写入到文件之前,文件内容首先会被清空。
重定向将输入文本通过追加模式保存到文件:
echo "this is a text line one" >> test.txt
写入到文件之后,会追加到文件结尾。
标准错误输出:
[root@localhost text]# cat linuxde.net
cat: linuxde.net: No such file or directory
标准错误输出的重定向方法:
方法一: [root@localhost text]# cat linuxde.net 2> out.txt //没有任何错误提示,正常运行。 方法二: [root@localhost text]# cat linuxde.net &> out.txt
因为错误信息被保存到了out.txt文件中。
[root@localhost text]# cat linuxde.net 2> /dev/null
将错误输出丢弃到/dev/null中,/dev/null是一个特殊的设备文件,这个文件接受到任何数据都会被丢系,通常被称为位桶、黑洞。
*tee命令
tee命令可以将数据重定向到文件,另一方面还可以提供一份重定向数据的副本作为后续命令的stdin。
在终端打印stdout同时重定向到文件中:
ls | tee out.txt
[root@localhost text]# ls | tee out.txt | cat -n
*重定向脚本内的文本片段(多行文本)
#!/bin/bash cat <<EOF>text.log this is a text line1 this is a text line2 this is a text line3 EOF
在cat <<EOF>text.log与下一个EOF行之间的所有文本都会当作stdin数据输入到text.log中。
自定义文件描述符
除了0、1和2分别是stdin、stdout和stderr的系统预留描述符,我们还可以使用exec命令创建自定义文件描述符,文件的的打开模式有只读模式、截断模式和追加模式。
< 操作符用于从文件中读取至stdin:
echo this is a test line > input.txt exec 3<input.txt //自定义文件描述符3打开并读取文件
在命令中使用文件描述符3:
cat <&3 this is a test line
这里需要注意只能读取一次,如果再次使用需要重新创建文件描述符。
自定义文件描述符
除了0、1和2分别是stdin、stdout和stderr的系统预留描述符,我们还可以使用exec命令创建自定义文件描述符,文件的的打开模式有只读模式、截断模式和追加模式。
< 操作符用于从文件中读取至stdin:
echo this is a test line > input.txt exec 3<input.txt //自定义文件描述符3打开并读取文件
在命令中使用文件描述符3:
cat <&3 this is a test line
这里需要注意只能读取一次,如果再次使用需要重新创建文件描述符。
> 操作符用于截断模式的文件写入(数据在文件内容被截断之后写入):
exec 4>output.txt echo this is a new line >&4 cat output.txt this is a new line
>> 操作符用于追加模式的文件写入(添加数据到文件中,原有数据不会丢失):
exec 5>>output.txt echo this is a appended line >&5 cat output.txt this is a new line this is a appended lin
=====================================================================
数组、关联数组和别名使用
数组:它借助索引将多个独立的数据存储为一个集合。
普通数组只能使用整数作为数组的索引值。
定义数组
格式:array[key]=value
单行一列值:
array_pt=( 1 2 3 4 5 6 )
一组索引值:
array_pt[0]="text1" array_pt[1]="text2" array_pt[2]="text3" array_pt[3]="text4" array_pt[4]="text5" array_pt[5]="text6"
ex:
[root@hadoop Desktop]# read -a array_pt
text1 text2 text3 text4 text5 text6 text7 text8
打印数组
打印指定索引的数组元素内容:
#echo ${array_pt[0]}
text1
index=3
#echo ${array_pt[$index]}
text4
打印数组中的所有值:
#echo ${array_pt[*]}
或者
#echo ${array_pt[@]}
打印数组长度(即数组中元素的个数):
#echo ${#array_pt[*]}
删除数组:
unset array_pt[1] //删除数组中第一个元素 unset array_pt //删除整个数组
数组的提取:
例如定义了数组 array=( [0]=one [1]=two [2]=three [3]=four )
${array[@]:0} //提取所有元素
${array[@]:1} //提取第一个元素后的所有元素
#echo ${array[@]:0:2}
one two
#echo ${array[@]:1:2}
two three
数组元素匹配:
左边开始最短的匹配:"t*e",这将匹配到"thre"
#echo ${array[@]#t*e}
one two e four
左边开始最长的匹配,这将匹配到"three"
#echo ${array[@]##t*e}
从字符串的结尾开始最短的匹配
#echo ${array[@]%o}
one tw three four
从字符串的结尾开始最长的匹配
# echo ${array[@]%%o}
one tw three four
子串替换:
#echo ${array[@]/o/m}
mne twm three fmur
没有指定替换子串,则删除匹配到的子符
#echo ${array[@]//o/}
ne tw three fur
替换字符串前端子串
#echo ${array[@]/#o/k}
kne two three four
替换字符串后端子串
#echo ${array[@]/%o/k}
one twk three four
关联数组
关联数组从bash 4.0开始被引入,关联数组的索引值可以使用任意的文本。关联数组在很多操作中很有用。
关联数组的声明:
declare -A array_var
使用内嵌索引-值列表法将元素添加到关联数组:
array_var=( [one]=one-1 [two]=two-2 [three]=three-3 [four]=four-4 [five]=five-5 [six]=six-6 )
使用独立的索引-值进行赋值:
array_var[one]=one-1 array_var[two]=two-2 array_var[three]=three-3 array_var[four]=four-4 array_var[five]=five-5 array_var[six]=six-6
关联数组的打印方法跟普通数组用法一样。
列出数组索引值:
#echo ${!array_var[*]}
four one five six two three
列出索引值的方法也可以用在普通数组上。
别名
别名就是提供一种便捷的方式来完成某些长串命令的操作。省去不必要的麻烦,提高效率。一般可以是函数或者alias命令来实现。
alias举例
alias nginxrestart='/usr/local/webserver/nginx/sbin/nginx -s reload'
这样设置之后以后可以使用nginxrestart这个命令来代替/usr/local/webserver/nginx/sbin/nginx -s reload了。这样设置重启之后就会失效,所以需要将它放入~/.bashrc文件中。
echo 'alias nginxrestart="/usr/local/webserver/nginx/sbin/nginx -s reload"' >> ~/.bashrc
查看系统已经定义的别名
[root@mail text]# alias
别名转义
有些命令不是总是希望使用别名,可以在命令之前输入反斜杠\来忽略所定义过的别名。
#\command
浙公网安备 33010602011771号