Shell是Linux系统的用户界面,它提供用户与内核的一种交互方式。它接收用户输入的命令,并把它送入内核去执行,是一个命令解释器,,它的作用就是遵循一定的语法将输入的命令加以解释并传给系统。Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言(就是你所说的shell脚本)。作为命令语言,它互动式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高阶语言中才具有的控制结构,包括循环和分支。它虽然不是 Linux系统内核的一部分,但它调用了系统内核的大部分功能来执行程序、创建文档并以并行的方式协调各个程序的运行。
echo $PASH
命令。chmod +x xxx.sh
为给文件添加可执行权限#!
用来声明脚本由什么shell解释,否则使用默认shell
#!/bin/sh
单个"#"号代表注释当前行 在脚本中定义的变量,脚本结束后,变量和它的值还在,命令行 可以通过typeset或declare可以设置变量类型。 使用一个定义过的变量,只要在变量名前面加美元符号$即可,如: 运行shell时,会同时存在三种变量: $#:传给 shell 脚本参数的数量 计算字符串长度 提取子串 拼接字符串 查找字符串 替换字符 基本用法 扩展用法 文件/目录判断: 字符串判断 数值判断 逻辑判断 其他判断 case 语句和 if…elif…else 语句一样都是多分支条件语句,不过和多分支 if 条件语句不同的是,case 语句只能判断一种条件关系,而 if 语句可以判断多种条件关系。 Linux中绝大多数命令都提供了 一般来说,短选项: 可以通过一个短横线"-“将多个短选项连接在一起,但如果连在一起的短选项有参数的话,则必须作为串联的最后一个字符。 短选项的参数可以和选项名称连在一起,也可以是用空白分隔。例如 如果某个短选项的参数是可选的,那么它的参数必须紧跟在选项名后面,不能使用空格分开。至于为什么,见下面的第3项。 一般来说,长选项: 下面这个是最常用的getopt解析方式(有这个命令就够了)。如果要了解getopt更完整的语法,见man getopt。 其中: getopt使用"-o"或"-l"解析短、长选项和参数时,将会对每个解析到的选项、参数进行输出,然后不断放进一个字符串中。这个字符串的内容就是完整的、规范化的选项和参数。 getopt使用"-o"选项解析短选项时: getopt使用"-l"选项解析长选项时: 例如在脚本test.sh中,下面的getopt的结果保存到变量parameters中,然后输出getopt解析完成后得到的完整参数列表。 执行这个脚本,并给这个脚本传递一些选项和参数,这些脚本参数将被收集到$@,然后被getopt解析。 首先可以看出,传递给脚本的参数都是无序的: 从getopt的输出结果中,可以看出: getopt解析得到了完整、规范化的结果,当然要拿来应用。例如直接传递个函数,或者根据while、case、shift将选项、参数进行分割单独保存。 如果要进行分割,由于getopt的解析结果通常保存在一个变量中,要解析这个结果字符串,需要使用eval函数将变量的内容进行还原,一般来说会将其设置为一个位置参数(因为shift只能操作位置变量)。 一般来说,整个处理流程是这样的:
<# 这里是注释
<<EOF
这里是多行注释
这里是多行注释
这里是多行注释
EOF
3.3 变量
variable=value #普通赋值方法
variable='value'
variable="value" #当变量的值(字符串)中包含任何空白符时,加双引号
echo $变量名
可以查看。# 表示将data设置为int型
typeset -i data
value="严长生"
echo $value
echo ${value}
形式
说明
$(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的值。
3.4 变量的作用域
3.5 输出echo
3.6 Shell预定义变量
$*:传给 shell 脚本参数的内容
$1、$2、$3、、$9:运行脚本时传递给其的参数,用空格隔开
$?: 命令执行后返回的状态
$?:用于检查上一个命令执行是否正确(在Linux中,命令退出状态为0表示该命令正确执行,任何非0 值表示命令出错)。
$0:当前执行的进程名
$$:当前进程的进程号
$$:变量最常见的用途是用作临时文件的名字以保证临时文件不会重复3.7 字符串操作
string="abcd"
echo ${#string} #输出 4
string="alibaba is a great company"
echo ${string:1:4} #输出liba
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
string="alibaba is a great company"
echo `expr index "$string" is`
text="read phy addr: 0x1f reg: 0x1f value : 0x0"
str="value : "
value=${text#*$str}
#打印value的值
echo "$value"
0x0
string="123123"
echo ${string/3/0} #用0替换第一个遇见的3
echo ${string//3/0} #用0替换串中所有3
3.8 if语句
if [ command ]; then
符合该条件执行的语句
fi
if [ command ];then
符合该条件执行的语句
elif [ command ];then
符合该条件执行的语句
else
符合该条件执行的语句
fi
常用的:
[ -a FILE ] 如果 FILE 存在则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。
[ -e FILE ] 如果 指定的文件或目录存在时返回为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。
[ -r FILE ] 如果 FILE 存在且是可读的则返回为真。
[ -w FILE ] 如果 FILE 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是可执行的)
[ -x FILE ] 如果 FILE 存在且是可执行的则返回为真。
不常用的:
[ -b FILE ] 如果 FILE 存在且是一个块文件则返回为真。
[ -c FILE ] 如果 FILE 存在且是一个字符文件则返回为真。
[ -g FILE ] 如果 FILE 存在且设置了SGID则返回为真。
[ -h FILE ] 如果 FILE 存在且是一个符号符号链接文件则返回为真。(该选项在一些老系统上无效)
[ -k FILE ] 如果 FILE 存在且已经设置了冒险位则返回为真。
[ -p FILE ] 如果 FILE 存并且是命令管道时返回为真。
[ -s FILE ] 如果 FILE 存在且大小非0时为真则返回为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID位时返回为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则返回为真。
[ -G FILE ] 如果 FILE 存在且默认组为当前组则返回为真。(只检查系统默认组)
[ -L FILE ] 如果 FILE 存在且是一个符号连接则返回为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则返回为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则返回为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 比 FILE2 新, 或者 FILE1 存在但是 FILE2 不存在则返回为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 老, 或者 FILE2 存在但是 FILE1 不存在则返回为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则返回为真。
[ -z STRING ] 如果STRING的长度为零则返回为真,即空是真
[ -n STRING ] 如果STRING的长度非零则返回为真,即非空是真
[ STRING1 ] 如果字符串不为空则返回为真,与-n类似
[ STRING1 == STRING2 ] 如果两个字符串相同则返回为真
[ STRING1 != STRING2 ] 如果字符串不相同则返回为真
[ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则返回为真。
[ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则返回为真。
[ INT1 -eq INT2 ] INT1和INT2两数相等返回为真 ,=
[ INT1 -ne INT2 ] INT1和INT2两数不等返回为真 ,<>
[ INT1 -gt INT2 ] INT1大于INT2返回为真 ,>
[ INT1 -ge INT2 ] INT1大于等于INT2返回为真,>=
[ INT1 -lt INT2 ] INT1小于INT2返回为真 ,<
[ INT1 -le INT2 ] INT1小于等于INT2返回为真,<=
[ ! EXPR ] 逻辑非,如果 EXPR 是false则返回为真。
[ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。
[ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。
[ ] || [ ] 用OR来合并两个条件
[ ] && [ ] 用AND来合并两个条件
[ -t FD ] 如果文件描述符 FD (默认值为1)打开且指向一个终端则返回为真
[ -o optionname ] 如果shell选项optionname开启则返回为真
3.9 case 语句
case $变量名 in
"值 1")
;;
如果变量的值等于值1,则执行程序1,值
2")
如果变量的值等于值2,则执行程序2
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
四.Shell中的getopt解析
1. Shell中的选项说明
短选项
和长选项
。一般来说,短选项是只使用一个"-“开头,选项部分只使用一个字符,长选项是使用两个短横线(即”–“)开头的。例如”-a"是短选项,"–append"是长选项。一般来说,选项的顺序是无所谓的,但并非绝对如此,有时候某些选项必须放在前面,必须放在某些选项的前面、后面。
例如”-avz
"其实会被解析为"-a -v -z
",tar -zcf a.tar.gz
串联了多个短选项,但"-f
"选项有参数a.tar.gz
,所以它必须作为串联选项的最后一个字符。-n 3
和-n3
是等价的,数值3都是"-n"选项的参数值。
--file=FILE
或--file FILE
。2. getopt解析
getopt -o SHORT_OPTIONS -l LONG_OPTIONS -n "$0" -- "$@"
-o SHORT_OPTIONS
和--options SHORT_OPTIONS
getopt通过"-o"选项收集命令行传递的短选项和它们对应的参数。-l LONG_OPTIONS
和--longoptions LONG_OPTIONS
getopt通过"-l"选项收集命令行传递的长选项和它们对应的参数。可能从别人的脚本中经常看到"–long",是等价的,前文已经解释过,长选项只要不产生歧义,是可以进行缩写的。关于LONG_OPTIONS的格式见下一小节。-n NAME
getopt在解析命令行时,如果解析出错(例如要求给参数的选项没带参数,使用了无法解析的选项等)将会报告错误信息,getopt将使用该NAME作为报错的脚本名称。-- "$@"
其中–表示getopt命令自身的选项到此结束,后面的元素都是要被getopt解析的命令行参数。这里使用"$@",表示所有的命令行参数。注意,不能省略双引号。
3. 示例分析getopt的解析方式
#!/usr/bin/env bash
parameters=`getopt -o ab:c:: --long add:,remove::,show -n "$0" -- "$@"`
echo "$parameters"
$ ./test.sh -a non-op_arg1 -b b_short_arg non-op_arg2 --rem --add /path --show -c non-op_arg3
-a -b 'b_short_arg' --remove '' --add '/path' --show -c '' -- 'non-op_arg1' 'non-op_arg2' 'non-op_arg3'
--rem
:是–remove的缩写形式,它的参数是可选的,但没有为它传递参数--add
:并设置了该选项的参数/path--show
:没有任何参数
-a
:它是无需参数的选项,所以它后面的non-op_arg1是一个非选项类型的参数-b
:它是必须带参数的选项,所以b_short_arg是它的参数-c
:它的参数是可选的,这里没有给它提供参数(前面解释过,要给参数可选的选项提供参数,短选项时,参数和选项名称必须连在一起)。
4.处理getopt解析的结果
parameters=$(getopt -o SHORT_OPTIONS -l LONG_OPTIONS -n "$0" -- "$@")
[ $? != 0 ] && exit 1
eval set -- "$parameters" # 将$parameters设置为位置参数
while true ; do # 循环解析位置参数
case "$1" in
-a|--longa) ...;shift ;; # 不带参数的选项-a或--longa
-b|--longb) ...;shift 2;; # 带参数的选项-b或--longb
-c|--longc) # 参数可选的选项-c或--longc
case "$2" in
"")...;shift 2;; # 没有给可选参数
*) ...;shift 2;; # 给了可选参数
esac;;
--) ...; break ;; # 开始解析非选项类型的参数,break后,它们都保留在$@中
*) echo "wrong";exit 1;;
esac
done