Shell
- 一、简介
- 二、语法
- 0. 注释
- 1. 变量
- 2. 数组
- 3. 传递参数
- 4. 运算符
- 5. 输入输出
- 5.1 echo
- 5.2 printf
- 5.3 输入输出重定向
- 6. test
- 7. 流程控制
- 7.1 if
- 7.2 for
- 7.3 while, until
- 7.4 case
- 8. 函数
- 9. 文件包含
- 三、技巧
vim调试,/{匹配字符}可以查找相应的位置,N往后查找下一个,shift N往前。
一、简介
Linux的Shell种类众多,常见的有:(一般不区分前两种)
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
- ……
#!
告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序
./{shell-name}.sh告诉系统说,就在当前目录找。写成{shell-name}.sh通常找不到命令的,因为linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH里,你的当前目录通常不在PATH里。
- 运行方法一
chmod a x ./test.sh # 添加 执行权限x(读r写w执行x,用户u用户组g其他o所有人a)
./test.sh
- 运行方法二 直接运行解释器,其参数就是shell脚本的文件名
/bin/sh test.sh
二、语法
特殊符号含义大全
两个反引号
表示整体作为一个字符串处理。
0. 注释
sh里没有多行注释,只能每一行加一个#号。
建议使用{}
将需要注释的代码块框起来,定义为函数的形式,模拟注释的效果。
1. 变量
变量名和等号之间不能有空格 使用一个定义过的变量,只要在变量名前面加美元符号$即可,赋值不用加 字符串可以用单引号,也可以用双引号,也可以不用引号。 双引号优点:可以有变量,可以出现转义字符。
代码语言:javascript复制# 获取长度
echo ${#string}
# 拼接字符串"",输出:hello, matthew!
stitch_string="hello, ${your_name}!"
echo ${stitch_string:1:4} #输出ello
# `用来将很多命令的结果保存到一个变量中去
2. 数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
代码语言:javascript复制array_name=(1 2 3)
array_name=(
1
2
3
)
# 可以不使用连续的下标,而且下标的范围没有限制
array_name[0]=value0
# 使用@或*符号可以获取数组中的所有元素
echo ${array_name[@]} # 输出:1 2 3
# 可配合#使用,获取数组长度
echo ${#array_name[*]} # 输出:3
3. 传递参数
脚本内获取参数的格式为:n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。 其中,0 为执行的文件名。
代码语言:javascript复制# $#: 传递到脚本的参数个数
# $*: 以一个单字符串显示所有向脚本传递的参数,$@类似
echo "$*"
./test.sh 1 2 3 # 输出: 1 2 3
# "$*"等价于"1 2 3"(传递了一个参数),而"$@"等价于"1" "2" "3"(传递了三个参数)
4. 运算符
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
表达式用esc
键下的反引号
扩起来,条件表达式要放在[]
中,并且运算符与参与运算的数之间要用空格隔开。
乘号(*)前边必须加反斜杠()才能实现。
echo `expr $a $b`
if [ $a != $b ] # []附近也要加“空格”
- 关系运算符
运算符 | 说明 |
---|---|
-eq | 检测两个数是否相等,相等返回 true |
-ne | 检测两个数是否相等,不相等返回 true |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true |
! | 非运算 |
-o | 或运算 |
-a | 与运算 |
&& | 逻辑的 AND,配合[]使用 |
|| | 逻辑的 OR,配合[]使用 |
-z(-n) | 检测字符串长度是否为(不为)0,为0返回 true |
文件测试符 | 略 |
5. 输入输出
read
命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量。
5.1 echo
-e
开启转义,n
换行,c
不换行。
#!/bin/sh
read input
echo -e "input is:n${input}c"
echo "."
# 输入:./test.sh -> hi
# 显示:input is:
# hi.
输入到指定文件
代码语言:javascript复制# 将"It is a test"输出到当前目录下的"myfile"文件中
echo "It is a test" > myfile # 可以写成“目录/文件名”的形式
原样输出字符串,不进行转义或取变量(用单引号)
显示命令执行结果
代码语言:javascript复制echo `date` # 反引号,date显示当前时间
5.2 printf
使用printf的脚本比使用echo移植性好。语法为printf format-string [arguments...]
,默认不换行。
# %-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
# %-4.2f 指格式化为小数,其中.2指保留2位小数。
printf "%-10s %-4.2fn" price 12.345
5.3 输入输出重定向
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
6. test
test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。 数值、字符的判断形式同上。
参数 | 说明 |
---|---|
-e 文件名 | 如果文件存在则为真 |
-r 文件名 | 如果文件存在且可读则为真 |
-w 文件名 | 如果文件存在且可写则为真 |
-x 文件名 | 如果文件存在且可执行则为真 |
-s 文件名 | 如果文件存在且至少有一个字符则为真 |
-d 文件名 | 如果文件存在且为目录则为真 |
-f 文件名 | 如果文件存在且为普通文件则为真 |
-c 文件名 | 如果文件存在且为字符型特殊文件则为真 |
-b 文件名 | 如果文件存在且为块特殊文件则为真 |
cd /bin
if test -e ./bash
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
7. 流程控制
提供了break
和continue
7.1 if
if语句经常与test命令结合使用,如果else分支没有语句执行,就不要写这个else。
代码语言:javascript复制if condition1
then
command1
elif condition2
command2
else
command3
fi
# 适用于终端输入
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
7.2 for
当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。
代码语言:javascript复制for ${var} in ${item1} ${item2} ... ${itemN}
do
command1
command2
...
commandN
done
for var in item1 item2 ... itemN; do command1; command2… done;
7.3 while, until
代码语言:javascript复制while condition
do
command
done
while(( $int<=5 )) do echo $int let "int " done
一般while循环优于until循环,但在某些时候—也只是极少数情况下,until循环更加有用。
7.4 case
取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。
代码语言:javascript复制case 值 in
模式1)
command1
;; # 类似break
模式2)
command2
;;
*) # 没有匹配
command3
;;
esac
8. 函数
函数返回值在调用该函数后通过 $?
来获得。所有函数在使用前必须定义。
# []内的为固定格式,其中function可选
[ function ] funname [()]
{
action;
[return ${int};]
}
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum $anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
9. 文件包含
Shell 也可以包含外部脚本。
代码语言:javascript复制. filename # 注意点号(.)和文件名中间有一空格
或
source filename
三、技巧
/dev/null:代表linux的空设备文件,所有往这个文件里面写入的内容都会丢失,俗称“黑洞” 即不显示任何信息。 放在>后面的&(&>和>&一样),表示重定向的目标不是一个文件,而是一个文件描述符。
代码语言:javascript复制mkdir -p /opt/mateinfo/{profile,logs} > /dev/null
# 内置的文件描述符,/dev下
1 => stdout
2 => stderr
0 => stdin
# >存在顺序问题,下述为将输出结果重定向到文件list中,此时list作为stdout,再将stderr重定向到stdout,即文件list
find /etc -name .bashrc > list 2>&1