Shell基础之变量、判断、逻辑控制
首先我们来看看维基关于shell的介绍
Shell(也称为壳层)在计算机科学中指“为用户提供用户界面”的软件,通常指的是命令行界面的解析器。一般来说,这个词是指操作系统中提供访问内核所提供之服务的程序。Shell也用于泛指所有为用户提供操作界面的程序,也就是程序和用户交互的层面。因此与之相对的是内核(英语:Kernel),内核不提供和用户的交互功能。
大白话就是和操作系统交互用的。我们现在用的比较多的是图形用户界面(GUI),简单易用直观的操作界面。命令行界面(CLI),是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,也有人称之为字符用户界面(CUI),功能复杂但是强大。
shell种类
- 常用shell:bash、sh、zsh
- Windows:git bash、cygwin、xshell
- Mac:Terminal、iTerm
变量
变量名=变量值
1 | a=1 |
这里有几点注意事项:
- =左右不要有空格
- 如果内容有空格,需要使用单引号或双引号
- 双引号支持转义
$
开头的变量会被自动替换
变量的使用
1 | echo $a |
- 使用
$var
或${var}
访问变量。后者更严谨。同时,$var_x
和${var}_x
是不同的 - 变量无需定义也可以使用,引用未定义的变量,默认值为空
预定义变量
1
2
3
4
5
6echo $PWD
echo $USER
echo $HOME
echo ~
echo $PATH
echo $RANDOM特殊符号的使用
- 双引号用于括起一段字符串值,支持 $var 形式的变量替换
- 单引号也表示其内容是字符串值,不支持转义
\
反斜线,某些情况下表示转义((a=a+3))
是整数扩展。把里面的变量当作整数去处理$(ls)
执行命令并把结果保存为变量 简写为``{1..10}
等价于seq1 10,表示1到10seq 1 3 10
表示生成一个1到10,步进为3变量类型
- 字符串
a="xx"
- 数字
i=1314
- 布尔
true false
- 数组
array=(a b c)
- 函数
foo() { echo hello world }
- 高于4.x的shell有hash词典功能
数字型变量操作
- 计算
i=1;echo $i;echo $((i+1))
- 更新
((i=i+1));echo $i
- 浮点数计算
awk 'BEGIN{print 1/3}'
- 格式化浮点数,保留小数点两位
awk 'BEGIN{printf("%.2f\n",1/3)}'
字符串的操作
${value:offset}
${value:offset:length}
从变量中提取字符串${#value}
字符串长度${#array[*]}
和${#array[@]}
表示数组中元素的个数${value#pattern}
${value##pattern}
#表示掐头${value%pattern}
${value%%pattern}
%表示去尾${value/pattern/string}
${value//pattern/string}
/ 表示替换- #与## %与%% /与//的区别:最短匹配模式VS最长匹配模式
${var/#Pattern/Replacement}
${var/%Pattern/Replacement}
- AWK可以代替这些操作,推荐AWK
例子
1
2
3
4
5
6
7xx="1234567";
echo ${xx:2:3};
echo ${xx/3/c};
echo ${xx# # *3};
echo ${x%%5*};
echo $xx | awk '{print substr($0,2,3)}'
echo $xx | sed 's#3#c#g'布尔变量
- true
- false
- 命令执行返回值$?
[ 2 -eq 2 ]
相等[ 2 -ne 2 ]
不等[ 3 -gt 1 ]
大于[ 3 -ge 3 ]
大于等于[ 3 -lt 4 ]
小于[ 3 -le 3 ]
小于等于(())
也可以表示算数比较。((10>=8))
字符串比较
[ str1 = str2 ]
如果两个字符串相同,则为真[ str1 != str2 ]
如果两个字符串不相同,则为真[ -n "$var" ]
如果字符串不是空,则为真[ -z "$var" ]
如果字符串是空,则为真[[ "xxxx" == x* ]]
在表达式中表示0或者多个字符[[ xxx == x?? ]]
在表达式中表示单个字符- 在引用变量的时候要记得加双引号
[ -z "$a" ]
,否则当a未定义时会报语法错误逻辑判断
[ 2 -ge 1 -a 3 -ge 4 ];echo $?
与[[ 2 -ge 1 && 3 -ge 4 ]];echo $?
与[ 2 -ge 1 -o 3 -ge 4 ];echo $?
或[[ 2 -ge 1 || 3 -ge 4 ]];echo $?
或[ ! 2 -ge 1 ];echo $?
非内置判断
-e file
文件存在,则为真-d file
文件是一个子目录,则为真-f file
文件是一个普通文件,则为真-r file
文件可读,则为真-s file
文件长度不为0,则为真-w file
文件可写,则为真-x file
文件可执行,则为真[[]]
是[]
的扩展语法,在老sh里面不支持,推荐用后者数组变量
array=(1 3 4 6)
array=('ls')
array[2]="hello world"
echo ${array[2]}
echo ${array[*]}
echo ${#array[*]}
- 使用
()
来定义数字变量,中间使用空格分开
逻辑控制
- 条件
if
- 分支
case
、select
- 循环
for
、while
、until
break
和continue
- 常用的有
if
、for
、while
if结构
if [condition ];then ...;fi
if [condition ];then ...;else ...;fi
if [condition ];then ...;elif ...;fi
- 简单的逻辑可以使用
&&
||
代替 [ -f file ] && echo file exist || echo file not exist
- 条件可以用命令返回值代替
for循环
for((c1;c2;c3));
do
...;
done
for((i=0;i<10;i++));do echo $i;done
for遍历循环
- 用于递归数组,还可以递归以空格隔开的字符串序列。或者是某个命令的返回值。
for f in $array[*];
do
...
done
ss="aa bb cc";for x in $ss;do echo$x;done
for x in 'ls';do echo $x;done
ss=(aa bb cc "sss dd");for x in "${ss[@]]}";do echo $x;done
while循环
- while需要设置条件
i=0;
while((i<10));do
echo $i;((i+=1));
done
- 一行行的读取文件内容
while read line;do echo $line;done < /home/lighthouse/joplin/1
退出控制
return
函数返回exit
脚本进程退出break
退出当前循环continue
跳出当前循环,进入下一次循环
小实战:抽奖程序
要求:从名单中抽出一个中奖者
1 | seeds=$(while read line;do echo ${line// /..};done < 名单.txt) |