IFS的默认值为:空白(包括:空格,制表符,换行符).
Linux脚本开头
#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面根的是此解释此脚本的shell的路径。
其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。
比如/bin/csh
脚本,/bin/perl
脚本,/bin/awk
脚本,/bin/sed
脚本,甚至/bin/echo
等等。
Shell脚本执行权限
给shell脚本添加执行权限,可以简单的通过./mine_shell.sh
来执行脚本,否则只能通过sh mine_shell.sh
执行脚本。
# 修改脚本执行权限
chmod +x mine_shell.sh
变量
shell编程中分为两种变量,第一种是我们自己定义的变量(自定义变量), 第二种是Linux已定义的环境变量(环境变量, 例如:$PATH, $HOME 等…, 这类变量我们可以直接使用)。
自定义变量和系统环境变量的用法,使用很简单,就是使用$符号加上变量名就行了。记住:定义变量不用$符号,使用变量要加$就行了。
我们在自定义变量时,使用了双引号,在shell编程中, 如果变量出现空格或者引号,那么也必须加引号, 否则就可以省略。还有一点需要注意,定义变量的时候,“=”左右千万不要有空格啊。
定义变量时使用单引号:赋值中不能出现空格,赋值中可以通过 $ 引用其他变量,此时单引号可以省略。
定义变量时使用双引号:赋值中可以包含转义字符类内容而不被识别,不能正常引用其他变量。
数据运算
整数运算
在shell中,有两种方式能实现整数运算,一种是使用expr命令, 另外一种是通过方括号($[])来实现。
#!/bin/bash
#输出13
expr 10 + 3
#输出10+3
expr 10+3
#输出7
expr 10 - 3
#输出30
expr 10 \* 3
#输出3
expr 10 / 3
#输出1
expr 10 % 3
#将计算结果赋值给变量
num1=$(expr 10 % 3)
#将计算结果赋值给变量
num2=`expr 10 % 3`
- 注意:
- 在以上的乘法(*)中,我们用了反斜线()来转义,不然会报错。
- 运算符前后必须还有空格,否则会被直接当作字符串返回。
- 如果要将计算结果保存到变量,就需要用到我们上篇文章讲到的那两种方式($() 或者 ``)来替换命令了。
整数运算推荐使用
方括号($[]):讲运算表达式包含在括号内,简单明了,避免歧义,推荐使用。
#!/bin/bash
num1=10
num2=3
#输出num1 + num2=13
echo "num1 + num2=$[$num1 + $num2]"
#输出num1+num2=13
echo "num1+num2=$[$num1+$num2]"
#输出num1 - num2=7
echo "num1 - num2=$[$num1 - $num2]"
#输出num1 * num2=30
echo "num1 * num2=$[$num1 * $num2]"
#输出num1 > num2=1
echo "num1 > num2=$[$num1 > $num2]"
#输出num1 < num2=0
echo "num1 < num2=$[$num1 < $num2]"
#将运算结果赋值给变量,输出num3=3
num3=$[$num1 / $num2]
echo "num3=$num3"
浮点运算
在shell中,做浮点运算一般是用bash的计算器(bc)。在shell脚本中,一般我们的使用方法是:
variable=$(echo "options; expression" | bc)
#!/bin/bash
#表示 10/3, 保留2位小数,将结果赋值给了num, 输出3.33
num=$(echo "scale=2; 10 / 3" | bc)
echo $num
条件选择
if-then语句
if command
then
commands
fi
----------------------------------------
if command; then
commands
fi
在shell脚本的if其实是根据紧跟后面的那个命令的退出状态码来判断是否执行then后面的语句的。
关于退出状态码,你只需要记住:正常退出(命令执行正常)的状态码是0, 非正常退出的状态码不是0(有不少)。
以上语句的语义为: 如果if后面的命令执行正常(状态码0),那么就执行then后面的语句。否则不执行。 fi代表if语句的结束。
if-then-else语句
if command; then
doSomeThing
else
doSomeThing
fi
----------------------------------------
if command1;then
doSomeThing
elif command2; then
doSomeThing
fi
test命令
test命令用于if-then或者if-then-else语句中,主要用于判断列出的条件是否成立,如果成立,就会退出并返回退出状态码0,否则返回非0。 这意味着我们可以通过test命令来写表达式命令了。
test命令只能判断一下三类条件:
- 数值比较
- 字符串比较
- 文件比较
数值比较
使用双括号
数值比较除了使用以上文本形式的比较符运算,还可以使用常规数学比较符,双括号命令(( expression ))
允许你在比较过程中使用高级数学表达式。
#!/bin/bash
num1=100
num2=200
if (( num1 > num2 )) ;then
echo "num1 > num2"
else
echo "num2 <= num2"
字符串比较
使用双方括号
双方括号命令提供了针对字符串比较的高级特性。它不仅解决了使用test所带来的一系列毛病,还提供了一些test命令所没有的高级用法。
双方括号命令的格式如:[[ expression ]]
case语句
语法:
case var in var变量
patten 1) 匹配模式1 a|b|c |和or类似
command... 需要执行的命令
;; 命令执行完毕
patten 2)
command...
;;
*) 默认值,没有匹配的模式
command...
;;
esac 代表case语句的结束
使用示例:
#!/bin/bash
case $num in
1)
echo "num=1";;
2)
echo "num=2";;
3)
echo "num=3";;
4)
echo "num=4";;
*)
echo "defaul";;
esac
for
for-in语句
list代表要循环的值,在每次循环的时候,会把当前的值赋值给var(变量名而已,随意定), 这样在循环体中就可以直接通过$var获取当前值了。
for var in list
do
commands
done
程序示例:
#!/bin/bash
# 根据空格将abcde分割,然后依次输出出来
for str in a b c d e
do
echo $str
done
造成这个结果的原因是:for…in循环默认是循环一组通过空格或制表符(tab键)或换行符(Enter键)分割的值。 这个其实是由内部字段分隔符配置的,它是由系统环境变量IFS定义的。当然,既然是由环境变量定义的,那当然也就能修改啊。
修改IFS值
#!/bin/bash
#定义一个变量oldIFS保存未修改前的IFS的值
oldIFS=$IFS
#修改IFS值,以逗号为分隔符
IFS=$','
list=a,b,c,d,e
list2="a b c d e"
for var in $list
do
echo $var
done
for var2 in $list2
do
echo $var2
done
#还原IFS的值
IFS=$oldIFS
C语言风格的for循环
bash中c语言风格的for循环遵循如下格式:
#!/bin/bash
for (( i = 0; i <= 10; i++ ))
do
echo $i
done
while循环
如果你习惯了其它语言的while循环,那么到这儿你又会发现这个while循环有点变态了。 与其它编程语言while的不同在于:在bash中的while语句,看起来似乎是结合了if-then语句(参考上一篇)和for循环语句。其基本格式如下:
while test command
do
other commands
done
until循环语句
在掌握while循环语句之后, until语句就很简单了。until语句就是与while语句恰好相反, while语句是在test命令退出状态码为0的时候执行循环, 而until语句是在test命令退出状态码不为0的时候执行。
#!/bin/bash
flag=0
until (( $flag > 10 ))
do
echo $flag
flag=$[ $flag + 1 ]
done
控制循环
- break用于跳出当前循环。
命令行参数处理
根据参数位置获取参数
bash shell可根据参数位置获取参数。通过 $1 到 $9 获取第1到第9个的命令行参数。$0为shell名。
如果参数超过9个,那么就只能通过${}来获取了, 例如获取第10个参数,那么可以写为${10}。
$0默认会获取到当前shell文件的名称,但是,它也包含(./),如果你以完整路径运行,那么这还会包含目录名。因此,上面通过basename命令来获取单纯的文件名$(basename $0)。
读取所有参数
在bash shell中通过 $# 可获取参数总数。
#!/bin/bash
# 获取参数总数,并依次读取
for (( index=0; index <= $#; index++ ))
do
echo ${!index}
done
我们通过 $# 获取总参数个数。然后通过循环获取每个位置的参数。注意: 按照正常的理解,上面的 ${!index}
应该是 ${$index}才对, 对吧?
但是,由于${}内不能再写$符号,bash shell在这个地方是用了!符号,所以以上才写为了${!index}。
在bash shell中还可以通过 $* 和 $@ 来获取所有参数。但是这两者之间有着很大的区别:
- $* 会将命令行上提供的所有参数当作一个单词保存, 我们得到的值也就相当于是个字符串整体.
- $@ 会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。
获取屏幕输入
我们在shell执行过程中获取用户的输入,以此与用户进行交互。这是通过read命令来实现的。下面就来看看其用法:
- 单个输入
#!/bin/bash # -n参数表示不换行 echo -n "yes or no(y/n)?" read choice echo "your choice: $choice"
事实上,我们可以不指定read后面的变量名,如果我们不指定, read命令会将它收到的任何数据都放进特殊环境变量REPLY中.
#!/bin/bash echo -n "yes or no(y/n)?" read echo "your choice: $REPLY"
- 多个输入
#!/bin/bash read -p "what's your name?" first last echo first: $first echo last: $last