《linux shell 脚本攻略》
一、小试牛刀
1、脚本是使用一种特定的描述性语言,依据一定的格式编写的可执行文件,又称作宏或批处理文件。
(1)脚本简单的说就是一条条的文字指令,这些命令是可以看到的,如可以用记事本打开、查看、编辑,脚本程序执行时,由系统的一个解释器,将其一条条的翻译成机器可识别的指令,并按程序顺序执行,因为脚本在执行多了一道翻译的过程,所以它比二进制程序执行效率要稍低一些;
(2)UNIX风格的操作系统架构最重要的一个特性是命令行界面或shell;
shell环境使得用户能与操作系统的内核进行交互操作。术语“脚本”更过涉及的是这类环境;编写脚本通常使用某种基于解释器的编程语言,而shell脚本不过是一些文件,我们能将一系列需要执行的命令写入其中,然后通过shell来执行这些脚本。
(3)$表示普通用户,#表示超级用户即root user,
shell脚本通常是一个以#!为起始的文本文件,如下所示:
#!/bin/bash
linux环境下的任何脚本语言都是以这样一个被称为shebang的特殊行作为起始的。字符#!被置于解释器路径之前,/bin/bash是Bash的路径
(4)脚本执行方式
有两种脚本执行的方式:一种是将脚本作为sh的命令行参数,另一种是将脚本作为具有执行权限的可执行文件。
第一种:将脚本作为命令行参数时的运行方式如下:
$ sh script.sh 假设脚本位于当前目录下
$ sh /home/path/script.sh 使用sript.sh的完整路径
如果将脚本作为sh的命令行参数来运行,那么脚本中的shebang行也就没什么用处了。
第二种:将脚本作为可执行文件来执行:
为了使shell脚本能够自己独立运行,需要具备可执行权限。要使脚本独立运行,必须利用shebang行,它通过使用位于#!之后的解释器来运行脚本,至于脚本的可执行权限,可以通过以下方式设置:
$ chmod a+x script.sh
该命令赋予所有用户script.sh文件的可执行权限,这个脚本能以下列方式执行:
$ ./script.sh ./表示当前目录
或者
$ /home/path/script.sh 使用脚本的完整路径
shell程序读取脚本的首行,查看shebang行是否为#!/bin/bash,它会识别/bin/bash,并且在内部以如下命令执行该脚本:
$ /bin/bash script.sh
当打开一个终端时,该终端最初会执行一组命令来定义诸如提示文本、颜色等各类设置。这组命令来自位于用户home目录中的.bashrc脚本文件(~/.bashrc)。Bash还维护了一个历史记录文件~/.bash_history,用于保存用户运行过的命令,~是一种简写,代表用户home目录的路径。
注:chmod命令解释:
变更文件或目录的权限。在UNIX系统家族里面,文件或目录权限的控制分别以读取、写入、执行3种一般权限来区分,另有三种特殊权限可供运用,再搭配拥有者与所属群组管理权限范围。你可以使用chmod指令去变更文件与目录的权限,设置方式采用文字或数字代号皆可。
权限范围的表示法如下:
u:user,即文件或目录的拥有者
g:Group,即文件或目录的所属群组
o:other,除了文件或目录拥有者或所属群组之外,其他用户皆属于这个范围
a:all,即全部用户,包含拥有者,所属群组以及其他用户
有关权限的代号,列表如下:
r:读取权限,数字代号为4
w:写入权限,数字代号为2
x:执行或切换权限,数字代号为1
-:不具任何权限,数字代号为0
s:特殊功能
范例一 :将档案 file1.txt 设为所有人皆可读取 :
chmod ugo+r file1.txt
将档案 file1.txt 设为所有人皆可读取 :
chmod a+r file1.txt
将档案 file1.txt 与 file2.txt 设为该档案拥有者,与其所属同一个群体者可写入,但其他以外的人则不可写入 :
chmod ug+w,o-w file1.txt file2.txt
将 ex1.设定为只有该档案拥有者可以执行 :
chmod u+x ex1
将目前目录下的所有档案与子目录皆设为任何人可读取 :
chmod -R a+r *
当其他用户执行oracle的sqlplus这个程序时,他的身份因这个程序暂时变成oracle
chmod u+s sqlplus
此外,chmod也可以用数字来表示权限:如 chmod 777 file
此外,chmod也可以用数字来表示权限如 chmod 777 file
语法为:chmod abc file
其中a,b,c各为一个数字,分别表示User、Group、及Other的权限。
r=4,w=2,x=1
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=5。
(5)Bash,每个命令或是命令序列是通过使用分号或换行符来分隔的。比如:
$ cmd1; cmd2
他等同于:
$ cmd1
$ cmd2
2、终端打印
终端作为交互式工具,用户可以通过它与shell环境进行交互,在终端中打印文本是绝大多数shell脚本和工具日常需要进行的基本任务。
echo是用于终端打印的的基本命令。
(1)只需要使用带双引号的文本,结合echo命令就可以将该文本在终端中打印出来。类似的,不带双引号的文本也可以得到同样的输出结果:
$ echo "welcome to Bash"
welcome to Bash
$ echo welcome to Bash
welcome to Bash
使用单引号也可以:
$ echo 'welcome to Bash'
welcome to Bash
注:当双引号和单引号之间没有字符时,不打印任何东西,但是双引号或单引号必须是偶数个,不然会一直提示你输入,知道你输入双引号或单引号
$ echo 'welcome to Bash'''
welcome to Bash
$ echo """"welcome to Bash ''''
welcome to Bash
$echo welcome to '''B
>a
>s
>h'
输出:
welcome to B
a
s
h
如果你希望打印!,那就不要将其放入双引号,或者是将其放入双引号时,在其之前加上一个特殊的转义字符\,将!转义:
$ echo !
!
$echo '!'
!
$echo "!"
-bash: !:event not found
$echo "\!"
!
但是在我的ubuntu上打印出来的是:
$echo "\!"
\!
$echo \!
!
printf在我的ubuntu上不能用
(2)默认情况下,echo会将一个换行符追加到输出文本的尾部,可以使用标志-n来忽略结尾的换行符。
如:
test@ubuntu:~$ echo -n "1234"
1234test@ubuntu:~$
而:
test@ubuntu:~$ echo "1234"
1234
test@ubuntu:~$
echo同样接受双引号字符串内的转义序列作为参数。如果需要使用转移序列,则采用
echo -e "包含转义序列的字符串"
例如:
echo -e “1\t2\t3”
1 2 3
这里就将\t作为制表符
(3)打印彩色输出:
打印彩色字体:
每种彩色都有对应的彩色码:比如:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37;
打印彩色字体可以输入:
echo -e "\e[31m This is a red text \e[0m"
This is a red text
其中\e[31m是将颜色设置成红色,\e[0m是将颜色重新置回,你只需要将颜色替换成你想要的颜色码就可以了。
要想设置彩色背景,经常使用的颜色码是:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47;
echo -e "\e[41m This is a red text \e[0m"
This is a red text
3、变量和环境变量
脚本语言中,通常不需要在使用变量之前声明其类型,只需要直接赋值就可以了;
在Bash中,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。
有一些特殊的变量会被shell环境和操作系统环境用来存储一些特别的值,这类变量就称为环境变量
(1)预备知识
对于每个进程,在其运行时的环境变量可以使用下面的命令来查看:
$ cat /proc/$PID/environ
其中,将PID设置成相关进程的进程PID,PID总是一个整数。
假设有一个叫做gedit的应用程序正在运行,我们可以使用pgrep命令获得gedit的进程ID:
$ pgrep gedit
12506
那么,你就可以通过以下命令获得与该进程相关的环境变量:
$ cat /proc/12506/environ
(2)实战演练
变量赋值:var=value
var是变量名,value是赋给变量的值,如果value不包含任何空白字符例如空格,那么它不需要使用引号进行引用,反之,则必须使用双引号。
注:var = value不同于var=value,把var=value写成var = value是一个常见的错误,前者是赋值操作,后者是比较相等操作;
在变量名前加上$前缀就可以打印出变量内容:
$ var="welcome"
$ echo $var
welcome
或者:
$ echo ${var}
welcome
环境变量是未在当前进程中定义,而从父进程中继承而来的变量。
export命令用来设置环境变量,至此之后,从当前shell脚本执行的任何程序都会继承这个变量。
$PATH通常定义在/etc/environment或/etc/profile或~/.bashrc中;
如果需要在PATH中添加一条新路径,可以使用:
$ export PATH="$PATH:/home/user/bin"
也可以使用:
$ PATH="$PATH:/home/user/bin"
$ export PATH
显示环境变量
$ echo $PATH
显示HOME:
$ echo $HOME
显示当前工作目录
$ echo $PWD
显示当前用户名
$ echo $USER
显示当前用户的ID
$ echo $UID
显示当前进程号
$ echo $PID
显示当前进程父进程号
$ echo $PPID
(3)补充内容
获得字符串长度:
length=${#var}
例如:
$ var=012346789
$ echo ${#var}
10
或者
$ var=0123456789
$ length=${#var}
$ echo $length
10
length就是字符串所包含的字符数。
(4)识别当前的shell版本,看一下使用的是那种shell
$ echo $SHELL
/bin/bash
或者使用:
echo $0
bash
(5)检查是否为超级用户
UID是一个重要的环境变量,可以用于检查当前脚本是以超级用户还是以普通用户的身份运行的。
if [ $UID -ne 0 ] ;then
echo Non root user.Please run as root.
else
echo "Root user"
fi
root用户的UID是0.
(6)修改Bash提示字符串
先列到这里
4、利用shell进行运算
利用let、[]、{}、()进行基本的算术运算
(1)使用let的时候,变量名之前不需要再添加$:
$ no1=4
$ no2=5
$ let result=no1+no2
$ echo $result
9
自加操作:
$ let no1++
$ let no2++
$ echo $no1;echo $no2
5
6
自减操作:
$ let no1--;let no2--
4
5
简写形式
$ let no1+=6;let no2-=6
$ echo $no1;echo $no2
10
-1
分别等同于:let no1=no1+6;let no2=no2-6
(2)操作符[ ]的使用方法和let命令类似:
$ result=$[no1+no2];echo $result
9
或者:
$ result=$[$no1+no2];echo $result
9
也可以使用(()):
$ result=$((no1+no2));echo $result
9
(3)也可以使用expr命令:
expr命令介绍:一般用于整数值计算,也可用于字符串操作;使用权限是所有使用者;格式是:
expr argument operator argument
参数说明:argument:第一个操作数
operator:为操作运算符
argument:第二个操作数
数学运算器:
注意运算符左右要有空格
$ expr 13 + 12
25
$ expr 13 - 12
1
$ expr 30 / 3
10
$ expr 30 / 2 / 5 可以使用这种连续的计算,加减乘除法均可以
3
$ expr 12 \* 5 使用乘号时,必须使用反斜线屏蔽其特定含义,因为shell可能会误解显示星号的含义。
60
增量计数:
expr在循环中用于增量计算,首先,循环初始化为0,然后循环值加1,反引号的用法意即替代命令,最基本的一种是从expr命令接受输出并将之放入循环变量。
$LOOP=0
$LOOP=`expr $LOOP + 1`
注意上面的 ` 是与 ~ 相对应的键,即反引号
计算字符串的长度
方法一:使用echo:
$ str=”0123456789“
$ echo ${#str}
10
方法二:使用expr
$ expr length ”$str“
10
expr中的expr index $string substring索引命令功能在字符串$string上找出substring中字符第一次出现的位置,若不找出expr index返回0或1
$ str="0123456789sdf"
$ expr index “$str” my
0
$ expr index “$str” reg5
6
$expr index ”$str“ 340dsf
1
expr 中的expr match $string substring命令在string字符串中匹配substring字符串,然后返回匹配到的substring字符串的长度,若找不到则返回0;
$ string=asdfghjklqwertyuiop
$ expr match $string 4164
0
$ expr match $string as.*
19
$ expr match $string sjfsj
0
在shell中可以用{string:position}和{string:position:length}进行对string字符串中字符的抽取。第一种是从position位置开始抽取直到字符串结束,第二种是从position位置开始抽取长度为length的子串。而用expr中的expr substr $string $position $length同样能实现上述功能。
$ string=123456789
$ echo ${string:3}
456789
$ expr ${string:3}
456789
$ expr ${string:3:5}
45678
$ expr substr $string 3 5
34567
注意:echo ${string:10:5}和 expr substr "$string" 10 5的区别在于${string:10:5}以0开始标号而expr substr "$string" 10 5以1开始标号。
删除字符串和抽取字符串相似${string#substring}为删除string开头处与substring匹配的最短字符子串,而${string##substring}为删除string开头处与substring匹配的最长字符子串。
$ str=145411111ddfffffdd313
$ echo ${str#1*1}
1111ddfffffdd313
$ expr ${str#1*1}
1111ddfffffdd313
$ echo ${str##1*1}
3
$ expr ${str##1*1}
3
$ expr ${str#4*1}
145411111ddfffffdd313
$ expr ${str##4*1}
145411111ddfffffdd313
必须是开头处开始匹配
替换子串${string/substring/replacement}表示仅替换一次substring相配字符,而${string//substring/replacement}表示为替换所有的substring相配的子串。
$ str=145411111ddfffffdd313
$ expr ${str/11/##}
1454##111ddfffffdd313
$ expr ${str//11/##]
1454####1ddfffffdd313
(4)可用于浮点数的计算
bc:bc是一个用于数学运算的高级工具,这个精密计算器包含了大量的选项。
$ echo "4*1.25" | bc
5
$ no=45;re=`echo "$no * 2.75" | bc`;echo $re
123.75
设定小数精度(数值范围)
$ echo "scale=20;1/3" | bc
0.33333333333333333333
进制转换:用bc可以将一种进制系统转换为另一种进制系统;
$ no=100
$ echo "obase=2;$no" | bc
1100100
$ no=1100100
$ echo "obase=10;ibase=2;$no" | bc
100
计算平方根以及平方
$ echo "sqrt(100)" | bc
10
$ echo "10*10" | bc
100
$ echo "10^10" | bc
10000000000
5、文件描述符和重定向
文件描述符是与文件输入、输出相关联的整数,它们用来跟踪已打开的文件;最常见的文件描述符是stdin、stdout、stderr。
(1)>
先清空原文件,再写入内容
(2)>>
将内容追加到现有文件的尾部
注:看上一条命令是否执行成功:
$ ls +
ls:can't access +;
$ echo $? 上一条命令ls + 执行不成功,所以返回2
2
$echo $? 上一条命令echo $?执行成功,所以返回0
0
6、数组
bash同时支持普通数组和关联数组;普通数组只能使用整数作为数组索引,而关联数组可以使用字符串作为数组索引
$ arr=(1 2 3 4 5 6)
$ echo ${arr[0]}
1
$ echo ${arr[*]} 打印出每个数组元素
1 2 3 4 5 6
$ echo ${arr[@]}
1 2 3 4 5 6
$ echo ${#arr[*]} 打印数组元素的长度
6
$ echo ${#arr[@]}
6
8、获得终端信息
(1)
*****************************************************************************************************************************************************************************************
2013年4月9日
*****************************************************************************************************************************************************************************************