LINUX下Bash-Script的用法
本篇内容介绍了"LINUX下Bash-Script的用法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
第一个Bash-Script
LINUX shell的种类非常之多,但是目前用得最为广泛的还是Bash,本文也是基于Bash的Shell环境。 下面是一个简单的示例:
#! /bin/shecho 'hello world!'
这就是一个最简单的shell脚本了。 第一行的#!
用来告诉系统,这个脚本用什么解释器来执行(说明:sh和bash本身是不同的Shell,但是在我目前用得CentOS7版本sh和bash是等价的,sh是一个指向bash的符号链接)。 echo
命令输出文本到屏幕
如何运行脚本
一种方式就是将脚本作为解释器的参数,如:
sh test.sh
第二种方式就是授予文件可执行权限
chmod +x test.sh或者chmod 755 test.sh执行脚本./test.sh
变量与参数
变量
Bash是一种弱类型的语言,你只需要直接定义变量名=value
即可。当需要引用这个变量的时候使用$var_name
或者${var_name}
即可。 $var_name
是${var_name}
的一种简写形式,但是在某些情况下只能使用${var_name}
,例如:
# 当需要连接两个变量your_id=${USER}-on-${HOSTNAME}# 或者会与其他字符串写在一起的时候echo '${num}instance running!'
所以建议在写shell的时候统一使用${var_name}
的风格。 bash中变量是弱类型的,那么不管你传给他的是字符串、数字或者数组他都统统会接收,有时候这就会导致一些问题,比如你想做个计算器,这时候传给了变量一个'ABCDEFG',那么这时候我们就想这个变量只能接收数字。又或者你想定义一个常量,不想用户修改。那么以上这些我们可以使用declare
来声明变量的一些属性。 declare常用参数如下:
-r 定义一个只读变量,也可以使用"readonly var_name"将变量定义为只读变量 -i 定义变量类型为整型 -a 定义变量类型为数组 -f 定义一个函数 -x 定义一个全局变量
当想删除一个变量的时候直接使用unset var_name
即可,注意这个命令不能删除只读变量。
参数
那么如何向一个脚本传递参数呢? 当我们想向一个脚本传递参数的时候,直接在执行脚本的命令后面跟参数即可:
sh ./test.sh parm1 parm2 parm3
在脚本中使用$n
(n是一个数字,如:$1获取第一个参数)来接收传入的参数即可。下面是可能经常用到的参数变量:
$0 当前脚本的文件名。 $n 传递给脚本或函数的参数。n是一个数字。例如,第一个参数是 $1 。 $# 传递给脚本或函数的参数个数。 $* 传递给脚本或函数的所有参数。 $@ 传递给脚本或函数的所有参数。被双引号 (" ")包含时与$*不同。 $? 上个命令的退出状态,或函数的返回值。 $_ 上一个命令的最后一个参数
我们经常用到的Linux命令中有一种叫option的东西,基本模式-optionname
或者--longoptionname
。如果在我们编写脚本的时候需要option的话,简单的脚本直接把他当普通参数手工处理即可,面对比较复杂的可以使用getopt或者getopt。 这里感觉有必要提一下set
这个命令,我觉得很牛逼、很厉害、很有用但是我从来没在脚本中使用过的命令。 set
命令用来改变内部脚本的变量或者选项。一种应用就是来改变options来影响脚本的行为。另一种应用就是利用set `commond`
的输出来重置位置参数。
Example
#!/bin/bashecho "Command-line argument #1 = $1"echo "Command-line argument #2 = $2"echo "Command-line argument #3 = $3"echo "--------------------------------------"echo "利用`uname -a`的输出来重置位置参数"set `uname -a`echo "Field #1 of 'uname -a' = $1"echo "Field #2 of 'uname -a' = $2"echo "Field #3 of 'uname -a' = $3"exit 0output:[root@localhost study]# sh test_set.sh one two threeCommand-line argument #1 = oneCommand-line argument #2 = twoCommand-line argument #3 = three--------------------------------------Sets the positional parameters to the output of the commond `uname -a`Field #1 of 'uname -a' = LinuxField #2 of 'uname -a' = localhost.localdomainField #3 of 'uname -a' = 3.10.0-514.el7.x86_64
数组
目前只支持一维数组!!!!!!!!!! 可以通过以下两种方式来为数组赋值:
#!/bin/bashmy_array=(A B C "D")my_array[4]=Fmy_array[5]="G"
通过${my_array[idx]}
来读取数组中的值,也可以通过${my_array[*]}
或${my_array[@]}
来一次性读取数组中的所有元素。通过${#my_array[*]}
或${#my_array[@]}
来获取数组长度。
#!/bin/bashmy_array=(A B C "D")my_array[4]=Fmy_array[5]="G123"echo "第一个元素:${my_array[0]}"echo "通过*来获取数组所有元素:${my_array[*]}"echo "通过@来获取数组所有元素:${my_array[@]}"echo "通过*来获取数组长度:${#my_array[*]}"echo "通过@来获取数组长度:${#my_array[@]}"output:[root@localhost study]# sh test_arr.sh 第一个元素:A通过*来获取数组所有元素:A B C D F G123通过@来获取数组所有元素:A B C D F G123通过*来获取数组长度:6通过@来获取数组长度:6
关于引号
反引号
反引号括起来的字符串被bash解释为命令行执行,并以它的输出结果取代整个反引号部分。
#! /bin/shstr=`echo $PATH`echo ${str}output:[root@localhost study]# sh qut.sh /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
单引号
单引号扩起来的字符都视作普通字符,所有特殊字符都会失去原油的意义。
#! /bin/shstr='${PATH}'echo ${str}output:[root@localhost study]# sh qut.sh ${PATH}
双引号
由双引号括起来的字符,除$、\、'、和"这几个字符仍是特殊字符并保留其特殊功能外,其余字符作为普通字符对待。
while与for
for循环
for循环的一般格式为
for var in [list]do commondsdone
下面来看个例子:
#!/bin/bash# 如果后面的list不加引号,则默认以空格分割for var in A B C Ddo echo "${var}"doneecho;echo# 会将引号内的内容当做一个元素for var in "A A" "B B B" "C C"do echo "${var}"doneecho;echo# 上面两种写法有点类似java的for-each# 如果你用过C,那么你对下面这种写法更熟悉for ((a=1, b=1; a <= 5 ; a++, b++))do echo -n "$a-$b "doneoutput:[root@localhost study]# sh for-loop.sh ABCDA AB B BC C1-1 2-2 3-3 4-4 5-5
while循环
while循环的一般格式为
while [ condition ]do commandsdone
Example:
#!/bin/bashwhile (( a <= 5 ))do echo -n "$a " let "a+=1"done
break与continue
break用来跳出整个循环,continue跳出本次循环。
算术运算
首先来看个例子:
#! /bin/bashb=1+2echo "${b}"output:[root@localhost study]# sh test.sh 1+2
默认情况下,bash中会把所有的赋值当做字符或字符串,所以看到的输出是1+2
而不是3
。 可以用以下三种方式来做算术运算。
#! /bin/bash# 1、使用`declare`来声明变量为整型。declare -i bb=1+2echo "declare:${b}"echo;echo# 2、let命令let "c=1+1"echo "let:${c}"echo;echo# 3、利用双括号将表达式括起来((d=2+3))echo "((表达式)):${d}"echo;echo# 4、利用单个方括号echo "[表达式]:$[1+2]"output:[root@localhost study]# sh test.sh declare:3let:2((表达式)):5[表达式]:3
test命令
首先需要注意的是在Linux中"0"表示成功。test命令用来检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
直接使用
test
这个命令[...]:继承自test命令,主要用来方便其他语言的程序员。
((...)): 返回其中表达式的计算结果
Example:
[root@localhost ~]# test 1 -lt 2[root@localhost ~]# echo $?0[root@localhost ~]# [ 1 -lt 2 ][root@localhost ~]# echo $?0[root@localhost ~]# [[ 2 -eq 2 ]][root@localhost ~]# echo $?0[root@localhost ~]# (( 2 == 2 ))[root@localhost ~]# echo $?0
数字测试
数值测试操作符:
-eq 或 == : 是否相等
-ne 或 != : 不等于
-gt 或 > : 大于
-lt 或 < : 小于
-ge 或 >= : 大于等于
-le 或 <= : 小于等于 注意:或选项的用法其实就是讲数字当做字符串来比较
Example:
#! /bin/sha=4b=5if [ ${a} -ne ${b} ]then echo "${a} is not equal to ${b}fiechoif [ ${a} != ${b} ]then echo "${a} is not equal to ${b}."fi
字符串测试
= : 判断两个字符串是否相等。if [ "$a" = "$b" ]
== : 判断两个字符串是否相等,=的一个同义词
!= : 判断字符串是否不等
< : 小于,根据ASCII的排序,注意在[ a < b ]需要转义,在[[ a < b ]]可以直接使用,>同理
: 大于,根据ASCII的排序
-z : 字符串是否为空,或长度为0
-n : 字符串是否非空
Example:
#! /bin/shstr1=""if [ -z ${str1} ]then echo "str1 is null"fiecho str1="abc"if [ -n ${str1} ]then echo "str1 is not null"fiechostr2="cdef"if [ "${str1}" != "${str2}" ]then echo "${str1} is not equal to ${str2}"fi
文件测试
下面列举一些常用的文件操作:
-e : 文件或目录是否存在
-f : 是否是一个文件(而非目录)
-d : 是否是目录
-s : 文件大小是否为0
-r : 是否对文件有读权限
-w : 是否对文件有写权限
-x : 是否对文件有执行权限
-O : 是否是文件所有者
-G :是否与文件组用户相同
Example:
#! /bin/shfilename="/study/bash/test_file.txt" if [ -e "${filename}" ]then echo "${filename} file exists."fiif [ -f "${filename}" ]then echo "${filename} is a regular file."fiif [ -s "${filename}" ]then echo "${filename} not a zero file."fi
if & case
if语句的一般格式:
if conditionthen commondsfi
if-else语句的格式
if condition1then commondselif condition2then commondselse commondsfi
case语句的一般格式:
case 值 in模式1) commonds ;;模式2) commonds ;;esac
在case语句中可以用*
号来匹配任意值。
函数
平时在一些简单的脚本里面基本用不到函数,但是在复杂的脚本中用来组织代码以及封装常用逻辑,在bash中还是很好用的东西。 函数的定义格式如下:
[ function ] funname [()]{ action; [return ${result};]}
1、我们可以function funname
方式来定义,也可以直接funname()
。 2、可以显示的加return来返回结果或者直接返回最后一条命令的执行结果。
Example:
#! /bin/shfun(){ echo "it's a function"}fun
向函数传递参数的形式类似执行脚本的传参:fun_name arg1 arg2
Example:
#! /bin/shfun(){ if [ ${1} -gt ${2} ] then echo "${1} bigger than ${2}." elif [ ${2} -gt ${1} ] then echo "${2} bigger than ${1}." else echo "${1} equal to ${2}." fi}fun 10 20
读取键盘的输入
可以通过read
命令来读取标准输入的值。下面用一个例子来看下在bash中read
的常用方式:
#! /bin/sh# 将读取到的值赋值给var1这个变量,当我们在行尾加\时,按回车会换到下一行继续输入read var1echo "var1 is ${var1}"echo "==============================="# 直接read,可以使用$REPLY来获取读取到的值readecho "read $REPLY"echo "==============================="# -r参数会按字符串解释\,而不会换行read -r mul_lineecho "mul_line:${mul_line}"echo "==============================="# 上面的方式都会在屏幕上打印输入值,在交互式的bash中是不友好的,我们可以加-s选项来屏蔽输入的打印read -s var2echo "dont echo input:${var2}"echo "==============================="# 有时候可能不希望一直等待用户输入,我们可以用-t选项来这只超时时间TIMELIMIT=5read -t $TIMELIMIT var3if [ -z ${var3}]then var3="time out"fiecho "timed read:${var3}"
下面是测试的输出
[root@localhost study]# sh read_test.sh read value to var2\new linevar1 is read value to var2new line===============================read had no varread read had no var===============================read with -r option\mul_line:read with -r option\===============================dont echo input:do not echo input===============================timed read:time out
字符串
在大多数编程语言中,字符串是非常重要、常用的数据类型。 1、字符串长度
${#string}
expr length $string
expr "$string" : '.*'
Example:
#! /bin/shstr1="fdhjksdf"echo "${#str1}"echo "`expr length ${str1}`"echo "`expr "${str1}" : '.*'`"
2、匹配子串长度
expr match "$string" '$substr_regxp'
expr "$string" : '$substr_regxp'
Example:
#!/bin/shstr1="str;str-str;strend"sub_regxp="[a-z]*;"echo "`expr match "${str1}" "${sub_regxp}"`"echo "`expr "${str1}" : "${sub_regxp}"`"
3、子串开始索引
expr index $string $substring
Example
#! /bin/shstr="abc;efg;higj"rgx_str=";.*;"echo "`expr index ${str} ${rgx_str}`"
4、字符串截取
${string:position}
截取从postition位置开始的字符串${string:position:length}
从position位置开始截取长度为length长的子串,postition的开始索引为0expr substr $string $position $length
从position位置开始截取长度为length长的子串,postition的开始索引为1expr match "$string" '$sub_regxp'
截取匹配正则的子串expr "$string" : '$sub_regxp'
截取匹配正则的子串
Example
#! /bin/shstr="abc;defg;hijk;lmnpq"echo "\${string:position}"echo "${str:4}"echo "==================================="echo "\${string:position:length}"echo "${str:4:4}"echo "==================================="echo "expr substr \$string \$position \$length"echo "`expr substr ${str} 5 4`"echo "==================================="sub_regxp=".*;\(.*\);"echo "expr match "\$string" '${sub_regxp}'"echo "`expr match "${str}" ${sub_regxp}`"echo "==================================="echo "expr "\$string" : '\$sub_regxp'"echo "`expr "${str}" : ${sub_regxp}`"output:[root@localhost study]# sh sub_str.sh ${string:position}defg;hijk;lmnpq===================================${string:position:length}defg===================================expr substr $string $position $lengthdefg===================================expr match $string '.*;\(.*\);'hijk===================================expr $string : '$sub_regxp'hijk
5、删除子串
${string#substring}
,从前面最小匹配删除${string##substring}
,从前面最长匹配删除${string%substring}
,从后面最小匹配删除${string%%substring}
,从后面最小匹配删除
Example
#! /bin/shstr=abcABC123ABCabcreg_str='a*C'echo ${str#$reg_str} # 123ABCabcecho ${str##$reg_str} # abcreg_str='b*c'echo ${str%$reg_str} # abcABC123ABCaecho ${str%%$reg_str} # a
6、子串替换
${string/substring/replacement}
从前面最小匹配替换${string//substring/replacement}
从前面最长匹配替换${string/#substring/replacement}
从后面最小匹配替换${string/%substring/replacement}
从后面最长匹配替换
Debug your Script
在bash中提供了相关的参数供我们进行脚本的调试追踪。
sh [-nvx] script.sh 参数: -n:不执行基本,只检查语法问题 -v:执行脚本前,先将脚本内容输出到屏幕上 -x:将使用到的内容显示到屏幕上
"LINUX下Bash-Script的用法"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!