1 给变量赋值时,“=”两边都不能留空格
2 Shell 的默认赋值是字符串赋值
var=1
var=$var+1
echo $var
打印出来的是1+1而不是2。
3 [ -f "somefile" ]
:判断是否是一个文件
[ -x "/bin/ls" ]
:判断/bin/ls是否存在并有可执行权限
[ -n "$var" ]
:判断$var变量是否有值
[ "$a" = "$b" ]
:判断
a和
b是否相等
4 if 语句:
if …; then
…
elif …; then
…
else
…
if
下面是一个简单的if语句:
#!/bin/bash
if [ ${SHELL} = "/bin/bash" ] ; then
echo "your login shell is the bash (bourne again shell)"
else
echo "your login shell is not bash but ${SHELL}"
fi
5 case 语句
case表达式可以用来匹配一个给定的字符串,而不是数字(可别和C语言里的switch…case混淆)。
case … in
…)
do something here ;;
esac
file命令可以辨别出一个给定文件的文件类型,如:file lf.gz,其输出结果为:
lf.gz: gzip compressed data, deflated, original filename,
last modified: Mon Aug 27 23:09:18 2001, os: Unix
我们利用这点写了一个名为smartzip的脚本,该脚本可以自动解压bzip2, gzip和zip 类型的压缩文件:
#!/bin/bash
ftype="$(file "$1")"
case "$ftype" in
"$1: Zip archive"*)
unzip "$1" ;;
"$1: gzip compressed"*)
gunzip "$1" ;;
"$1: bzip2 compressed"*)
bunzip2 "$1" ;;
*) echo "File $1 can not be uncompressed with smartzip";;
esac
你可能注意到上面使用了一个特殊变量$1,该变量包含有传递给该脚本的第一个参数值。也就是说,当我们运行:
smartzip articles.zip
$1 就是字符串 articles.zip。
6 Bash只提供一维数组,并且没有限制数组大小
7 对数组元素赋值
对数组元素赋值的一般形式是:数组名[下标]=值,例如:
$ city[0]=Beijing
$ city[1]=Shanghai
$ city[2]=Tianjin
一个数组的各个元素可以利用上述方式一个元素一个元素地赋值,也可以组合赋值。定义一个数组并为其赋初值的一般形式是:
数组名=(值1 值2 … 值n)
其中,各个值之间以空格分开。例如:
$ A=(this is an example of shell script)
$ echo ${A[0]} ${A[2]} ${A[3]} ${A[6]}
this an example script
$ echo ${A[8]}
由于值表中初值共有 7 个,所以 A 的元素个数也是 7 。 A[8] 超出了已赋值的数组 A 的范围,就认为它是一个新元素,由于预先没有赋值,所以它的值是空串。
若没有给出数组元素的下标,则数组名表示下标为 0 的数组元素,如 city 就等价于 city[0] 。
8 如果要列出数组中的所有元素,使用*或@作下标
9 获取数组元素的个数
$ echo ${#A[*]}
10 数值比较中常见的比较符
= -eq
!= -ne(not equal)
> -gt(greater than)
>= -ge(greater than or equal)
< -lt(less than)
<= -le
11 测试文件属性的常见参数
-r; -w; -x; -f; -d
12 字符串长度属性
-z(字符串长度为零)
-n(非零)
13 条件测试命令 test
语法:test 表达式 如果表达式为真,则返回真,否则,返回假。
$ test var1 -gt var2
$ test -r filename
$ test -z s1 如果串 s1 长度为零,返回真。
14 有限循环命令for…in…
语法:
for 变量名 in 字符串表
do
命令表
done
举例:
FILE="test1.c myfile1.f pccn.h"
for i in $FILE
do
cd ./tmp
cp $i $i.old
echo "$i copied"
done
for var in sss
sss是串行,串行是一些字符串的组合。for…in…的运作方式是把sss中的元素依次取出放入变量var中,并执行do和done之间的命令
15 判断字符的类型
范例:数字或者数字组合
能够返回结果,即程序退出状态是0,说明属于这种类型,反之不然
$ i=5;j=9423483247234;
$ echo $i | grep [0-9]*
5
$ echo $j | grep [0-9]*
9423483247234
$ echo $j | grep [0-9]* >/dev/null
$ echo $?
0
范例:字符组合(小写字母、大写字母、两者的组合)
$ c="A"; d="fwefewjuew"; e="fewfEFWefwefe"
$ echo $c | grep [A-Z]
A
$ echo $d | grep "[a-z]*"
fwefewjuew
$ echo $e | grep "[a-zA-Z]*"
fewfEFWefwefe
字母和数字的组合
$ ic="432fwfwefeFWEwefwef"
$ echo $ic | grep "[0-9a-zA-Z]*"
432fwfwefeFWEwefwef
范例:空格或者 Tab 键等
$ echo " " | grep " "
$ echo -e "\t" | grep "[[:space:]]" #[[:space:]]会同时匹配空格和TAB键
$ echo -e " \t" | grep "[[:space:]]"
$ echo -e “\t” | grep “” #为在键盘上按下TAB键,而不是字符
范例:匹配邮件地址
$ echo "test2007@lzu.cn" | grep "[0-9a-zA-Z\.]*@[0-9a-zA-Z\.]"
test2007@lzu.cn
16 /dev/null 和 /dev/zero 是非常有趣的两个设备,它们都犹如一个黑洞,什么东西掉进去都会消失殆尽;后者则是一个能源箱,你总能从那里取到 0,直到你退出。
17
∗和
@ 的区别
∗所有参数列表。如”
*"用「"」括起来的情况、以"
1
2 …
n”的形式输出所有参数。
@
所有参数列表。如”
@"用「"」括起来的情况、以"
1” “
2"…"
n” 的形式输出所有参数。
示例:
1 #!/bin/bash
2 #
3 printf "The complete list is %s\n" "$*"
结果:
[Aric@localhost ~]$ bash params.sh 123456 QQ
The complete list is 123456 QQ
1 #!/bin/bash
2 #
3 printf "The complete list is %s\n" "$@"
结果:
[Aric@localhost ~]$ bash params.sh 123456 QQ
The complete list is 123456
The complete list is QQ
因为有两个参数,所以”$@”输出了两次
18 字符串的长度
范例:计算某个字符串的长度
即所有字符的个数[这计算方法是五花八门,择其优者而用之]
$ var="get the length of me"
$ echo ${var} # 这里等同于$var
get the length of me
$ echo ${#var}
20
$ expr length "$var"
20
$ echo $var | awk '{printf("%d\n", length($0));}'
20
$ echo -n $var | wc -c
20
19 字符串操作_取子串
取子串的方法主要有两种:直接到指定位置求子串,字符匹配求子串。
范例:按照位置取子串
比如从什么位置开始,取多少个字符
$ var="get the length of me"
$ echo ${var:0:3}
get
$ echo ${var:(-2)} # 方向相反
me
$ echo `expr substr "$var" 5 3` #记得把$var引起来,否则expr会因为空格而解析错误
the
$ echo $var | awk '{printf("%s\n", substr($0, 9, 6))}'
length
awk 把 $var 按照空格分开为多个变量,依次为 $1,$2,$3,$4,$5
$ echo $var | awk '{printf("%s\n", $1);}'
get
$ echo $var | awk '{printf("%s\n", $5);}'
me
范例:匹配字符求子串
用 Bash 内置支持求子串
$ echo ${var%% *} #从右边开始计算,删除最左边的空格右边的所有字符
get
$ echo ${var% *} #从右边开始计算,删除第一个空格右边的所有字符
get the length of
$ echo ${var##* } #从左边开始计算,删除最右边的空格左边的所有字符
me
$ echo ${var#* } #从左边开始计算,删除第一个空格左边的所有字符
the length of me
可以这么理解 #和%是从左边还是右边开始计算的flag,${var#* }
,从左边开始计算,删除一个"*"
和一个" "
(空格);${var##* }
从左边开始计算,删除n个"*"
和" "
;${var% *}
从右边开始计算,删除一个" "
和"*"
;${var%% *}
从右边开始计算,删除n个" "
和"*"
对于字符串的截取,实际上还有一些命令,如果 head,tail 等可以实现有意思的功能,可以截取某个字符串的前面、后面指定的行数或者字节数。例如:
$ echo "abcdefghijk" | head -c 4
abcd
$ echo -n "abcdefghijk" | tail -c 4
hijk
20 字符串操作_查询字串
子串查询包括:返回符合某个模式的子串本身和返回子串在目标串中的位置。
范例:查询子串在目标串中的位置
貌似仅仅可以返回某个字符或者多个字符中字符第一次出现的位置
$ var="get the length of me"
$ expr index "$var" t
3
awk 却能找出字串,match 还可以匹配正则表达式
$ echo $var | awk '{printf("%d\n", match($0,"the"));}'
5
21 字符串操作_子串替换
用 {} 运算符
$ var="get the length of me"
$ echo ${var/ /_} #把第一个空格替换成下划线
get_the length of me
$ echo ${var// /_} #把所有空格都替换成了下划线了
get_the_length_of_me
用 awk,awk 提供了转换的最小替换函数 sub 和全局替换函数 gsub,类似 / 和 //
$ echo $var | awk '{sub(" ", "_", $0); printf("%s\n", $0);}'
get_the length of me
$ echo $var | awk '{gsub(" ", "_", $0); printf("%s\n", $0);}'
get_the_length_of_me
用 sed ,子串替换可是 sed 的特长
$ echo $var | sed -e 's/ /_/' #s <= substitude
get_the length of me
$ echo $var | sed -e 's/ /_/g' #看到没有,简短两个命令就实现了最小匹配和最大匹配g <= global
get_the_length_of_me
sed 还有专门的插入指令,a 和 i,分别表示在匹配的行后和行前插入指定字符
$ echo $var | sed '/get/a test'
get the length of me
test
$ echo $var | sed '/get/i test'
test
get the length of me
22 重定向
linux shell下常用输入输出操作符是:
- 标准输入 (stdin) :代码为 0 ,使用 < 或 <<
- 标准输出 (stdout):代码为 1 ,使用 > 或 >>
- 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>>
实例:
#将错误输出信息关闭掉
[chengmo@centos5 shell]$ ls test.sh test1.sh 2>&-
test.sh
[chengmo@centos5 shell]$ ls test.sh test1.sh 2>/dev/null
test.sh
#&[n] 代表是已经存在的文件描述符,&1 代表输出 &2代表错误输出 &-代表关闭与它绑定的描述符
#/dev/null 这个设备,是linux 中黑洞设备,什么信息只要输出给这个设备,都会给吃掉
#关闭所有输出
[chengmo@centos5 shell]$ ls test.sh test1.sh 1>&- 2>&-
#关闭 1 ,2 文件描述符
[chengmo@centos5 shell]$ ls test.sh test1.sh 2>/dev/null 1>/dev/null
#将1,2 输出转发给/dev/null设备
[chengmo@centos5 shell]$ ls test.sh test1.sh >/dev/null 2>&1
#将错误输出2 绑定给 正确输出 1,然后将 正确输出 发送给 /dev/null设备 这种常用
<p>[chengmo@centos5 shell]$ ls test.sh test1.sh &>/dev/null
#& 代表标准输出 ,错误输出 将所有标准输出与错误输出 输入到/dev/null文件
注意:
1、shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空。
23 命令替换
语法
`command` 使用反引号
下面的例子中,将命令执行结果保存在变量中:
#!/bin/bash
DATE=`date`
echo "Date is $DATE"
USERS=`who | wc -l`
echo "Logged in user are $USERS"
UP=`date ; uptime`
echo "Uptime is $UP"
24
变量替换
变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值
可以使用的变量替换形式:
形式 说明
${var} 变量本来的值
${var:-word}
如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word}
如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message}
如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word}
如果变量 var 被定义,那么返回 word,但不改变 var 的值。
请看下面的例子:
#!/bin/bash
echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}"
echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}"
unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var"
var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var"
echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"
运行结果:
Variable is not set
1 - Value of var is
Variable is not set
2 - Value of var is Variable is not set
3 - Value of var is
This is default value
4 - Value of var is Prefix
Prefix
5 - Value of var is Prefix
25
Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。
如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。
像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项,如下所示:
复制纯文本新窗口
$unset .f function_name
如果你希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件,这样每次登录后,在命令提示符后面输入函数名字就可以立即调用。
26 引号
单引号字符串的限制:
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
单引号字串中不能出现单引号(对单引号使用转义符后也不行)。
双引号的优点:
双引号里可以有变量
双引号里可以出现转义字符
27 文件包含
像其他语言一样,Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。
Shell 中包含脚本可以使用:
. filename
或
source filename
28 IFS
内部字段分隔符(Internal Field Seprator)