1. shell中的特殊变量
变量名 | 含义 |
---|---|
$0 | shell或shell脚本的名字 |
$* | 显示所有的参数(以一对双引号给出参数列表) |
$@ | 显示所有的参数(将各个参数分别加双引号返回) |
$# | 传递给脚本参数的个数 |
$_ | 代表上一个命令的最后一个参数 |
$$ | 代表所在命令的PID |
$! | 代表最后执行的后台命令的PID |
$? | 代表上一个命令执行后的状态 |
bash -n shell.sh # 查看是否有语法错误
bash -x shell.sh # 单步执行
2. 变量类型
- 本地变量
- 环境变量: export – 导出一个环境变量
- 局部变量
- 位置变量
cut -d ' ' -f 2 #截取以空格为单位,第二个区间的信息
cut -c 12-20 #截取12到20位之间的信息
lines=$(wc -l $1|cut -d ' ' -f 1)
echo "$1 一共有$lines行" '$lines' "$lines"
echo $lines
shift # 轮岗
shift 2 # 踢走2个参数
3. bash的循环语句
for : 遍历有限的元素列表
while , until : 遍历未知的元素列表
3.1. for语句的格式
for var_name in list # do如果与for在同一行,则用;隔开
do
循环体
done # 结束标志
示例
for userNo in {10..30} # {10..30}生成10到30之间的数
do
echo $userNo
done
for userNo in $(seq 10 15);do # $(seq 10 15)生成10到15之间的数
echo user$userNo
done
for (( i = 0; i < 10; i++ )); do
echo user$userNo
done
for str in "This is a string";do #若无引号,则按空格分割,依次循环
echo $str
done
3.2. while语句的格式
while [[ 1 ]]; do
echo 1;
done
4. 逻辑运算
注:如果将命令执行成功与否当成条件,则if语句后必须只跟命令本身,而不能引用(用``或$())
4.1 bash
- 弱类型
- 变量=值
任何变量无需事先声明,可直接使用
值默认为字符型:a=abc === b=”vsf” #双引号可省略赋值: a=1
增强型赋值:+=,-=,*=,/=,a= [ [ <script id="MathJax-Element-1" type="math/tex">[</script>a+1] === let a+=1 === let a++
字符原理: export PATH=$PATH::user/local/bin
4.2 算数运算
bash会对数字进行隐式的类型转换
let VAR_name=Integer_Value declare VAR_name=Integer_Value
- 操作符:+,-,,/,%,*(次方),皆为双目运算符:至少需要两个操作数
let res=$num1*$num2
let num1=$num1+9 === let num1+=9
除法没有小数部分,会直接省去,术语:元整除法
3. bash算数运算的方式
let a=$b+$c #let必须实现将结果赋值于一个变量
$[$a+$b] #不需赋值,直接引用结果
$(($a+$b)) #推荐方式,但与$[$a+$b]无显著区别
`` or $() #中间可进行命令运行
expr:可引用,参数之间必须有空格,否则无法识别
"The sum is `expr $a + $b`" 输出: The sum is 4
for var in `seq 10 15`; do === for var in $(seq 10 15);do === for var in {10..15};do
#statements
}
done
- 实现变量与字串的连接:{}
animal=pig
echo "There are lot $animals." 输出:There are lot .
echo "There are lot ${animal}s" 输出:There are lot pigs
4.3 逻辑运算: 与 或 非
命令都有其状态返回值:成功:0、真,失败:1-255
bash条件测试:每个命令执行结果即为条件判断
- 比较操作: test EXPR
test num1 > num2
echo $? # 0 为true,1-255为false
2. [ EXPR ]
3. [[ EXPR ]]
注:2 与 3 差别不大
2. 比较运算: > , < , <= , >= , != , ==
测试类型:根据比较时的操作数的类型
整型测试:整数比较
字符测试:字符串比较
文件测试:判断文件的存在性及属性等
注:比较运算通常在同一种类型中运行
整型测试:
-gt [ $num1 -gt $num2 ] 大于
-lt [ $num1 -lt $num2 ] 小于
-ge [ $num1 -ge $num2 ] 大于等于
-le [ $num1 -le $num2 ] 小于等于
-eq [ $num1 -eq $num2 ] 等于
-nq [ $num1 -nq $num2 ] 不等于
字符串测试:(字串必须用引号引起来)
双目操作符:
> [ "$str1" > "$str2" ]
<
>=
<=
==
!=
=~ 字段的模式匹配,一般用[[ ]]
注:做字串比较时,变量与字符串尽量加引号,变量加双引号,可防止变量为空时语法报错
弹幕字符串:
-n string 测试字符是否不空,不空为真
-z string 测试字符是否为空,空为真
3. if:三种使用格式
- 单分支的if
if 测试条件;then
选择分支
fi
if ! id $userid &> /dev/null;then # &> 只要返回状态码
useradd $userid
fi
- 双分支的if
if 测试条件;then
选择分支
else
选择分支
fi
- 多分支的if
if 条件1;then
分支1
elif 条件2;then
分支2
...
else
分支n
fi
自定义shell进程的状态返回值
若参数个数小于1,退出shell脚本
if [ $# -lt 1 ]; then echo "Usage : `basename $0` ARG" exit 2 fi
例:确认传入参数的最大值
declare -i max=0 for i in $*;do if [ $max -lt $i ]; then max=$i fi done echo "The max num is $max."
注意:如果将命令执行成功与否当成条件,则if语句后必须只跟命令本身,而不能引用(用“或$())
练习:通过命令行给定一个文件路径,而后判断,如果此文件中存在空白行,则显示空白行的次数,否则则显示无空白行
if grep "^[[:space:]]*$" $1;then
或者
if [ $(grep "^[[:space:]]*$" $1 | wc -l) -lt 1 ];then
练习:如果用户主机名为localhost,将其修改为www.wjb.com
if [[ `hostname` == 'localhost' ]]; then
hostname www.wjb.com
fi
练习:如果当前的主机名为空,则将其修改为用户通过参数传递过来的用户名
hostname=`hostname`
if [[ -z $hostname ]]; then
hostname $1
fi
组合条件测试:在多个条件间实现逻辑运算
与: [ condition1 -a condition2 ]
condition1 && condition2 condition 为命令行输入方式
或: [ condition1 -o condition2 ]
condition1 || condition2
非: [ -not condition ] or [ !condition ]
! condition
练习:如果当前的主机名为空或者为localhost,将其修改为www.wjb.com
hostname=`hostname`
if [[ -z "$hostname" -o "$hostname" = 'localhost' ]]; then
hostname www.wjb.com
fi
命令行可直接测试bool: [ 'localhost' == 'local' ];echo $? # 可查看语句执行状态返回值
>只能将正常信息重定向
&>可以将错误信息或者普通信息都重定向输出
练习:如果某用户存在,则显示id号(命令行操作不可用[]):
if id "wjb" &> /dev/null;then
id -u "wjb"
fi
练习:如果某用户存在,且answer变量的值为yes,则显示用户的id号,否则,说用户选择了退出
id 'wjb'
retVal=$?
if [[ "$retVal" -eq 0 -a "$answer" == 'yes' ]]; then
id -u "wjb"
else
echo '用户选择了退出'
fi
上述方式等同于:
if id 'wjb' &> test && [ $answer == 'yes' ]; then
id -u "wjb"
else
echo '用户选择了退出'
fi
练习:如果传入参数大于5,则count加1,最后输出count
#!/bin/bash
declare -i count=0
list=$*
echo $list
for str in $list;do
if [ "$str" -gt 5 ]; then
let count++
fi
done
echo $count
5. 文件测试常用功能
-a / -e file : 文件存在才则为真,否则则为假,也可能是目录等
if [[ -a test ]]; then
wc -l test
fi
-f file : 存在并且为普通文件,则为真,否则为假
-d file : 存在并且为目录时为真,否则为假
-L / -h file : 存在并且为符号链接文件,则为真,否则为假
-b file : 存在并且为块设备时为真,否则为假
-c file : 存在并且为字符设备时为真,否则为假
-S file : 存在并且为套接字文件时为真,否则为假
-p file : 存在并且为命名管道文件时为真,否则为假
-s file : 存在并且文件不为空时为真,否则为假
-r file
-x file
-w file
file1 -nt file2 : file1的 mtime 新于file2则为真,否则为假
file1 -ot file2 : file2的 mtime 新于file1则为真,否则为假
练习:如果wget命令对应的可执行文件存在且可执行,则下载百度首页于当前目录
#!/bin/bash
#
downUrl='www.baidu.com'
if [[ -x `which curl` ]]; then
curl $downUrl -o baidu.txt
fi
练习:给定一个文件路径
1. 判断文件是否存在,不存在,则说明文件不存在,并直接结束脚本
2. 如果文件是普通文件,则显示为’regular file’
3. 如果文件是目录,则显示为’directory’
4. 如果文件为链接文件,则显示为’Symbolic file’
5. 否则显示为’unknown file’
#!/bin/bash
if [[ ! -e $1 ]]; then
echo 'file is not exist'
fi
if [[ -L $1 ]]; then
echo 'Symbolic file'
elif [[ -f $1 ]]; then
echo 'regular file'
elif [[ -d $1 ]]; then
echo 'directory'
else
echo 'unknown file'
fi
bash编程之交互编程
read num1
增加提示信息:
read -p "Please input an interger:" num1
等价于
echo -n "Please input an interger:";read num1
添加超时判断,秒为单位:
read -p "Please input an interger:" -t 3 num1
添加默认值:
if [[ -z "$num1" ]]; then
num1='root'
fi
cat << EOF # 可将EOF间的内容直接输出到屏幕
----------menu-------------
----------menu-------------
----------menu-------------
EOF
字段的模式匹配:
[[ "$var" =~ PATTERN ]]
例:
var='cpu'
[[ "$var" =~ [Cc][Pp][Uu] ]]
echo $?