shell是一个用C编写的成语,是用户使用Linux的桥梁。它既是一种命令语言,又是一种程序设计语言。
Bash是一种运行shell脚本的解释器,是Linux默认使用的shell解释器。其它常见的shell解释器还有C Shell(csh)、z shell(zsh)等。shell脚本一般以.sh作为扩展名(仅作为辨识,不影响运行),且首行用以下语句指定shell解释器。#! /bin/bash
shell解释器的脚本,可以在命令行中给与可执行权限后直接运行。sudo chmod +x script.sh
./script.sh
shell解释器的脚本,可以用以下命令在运行时指定。此时文件中指定shell解释器的首行失效。(实际上是运行解释器,将脚本文件作为参数)/bin/bash script.sh
不同语句可以用换行符,也可以用分号分隔写在一行
当一行语句可以用()或{}括起来时,有不同的效果
()会开启一个子 Shell 执行;{}在 当前 Shell 中执行{}中第一条命令与左括号之间必须有一个空格,且最后一条命令一定要用分号;()不必()和{}括号里面的某条命令的重定向只影响该命令,但括号外的重定向则会影响到括号里的所有命令前一条语句执行不成功不影响后面语句的执行
=之间不能有空格(避免歧义,shell中常用空格做参数间的分隔符)。$,也可以用花括号将变量名括起来确定边界,例如:#! /bin/bash
name="yexiaowo"
echo "your name is $name."
echo "your name is ${name}."
用$+数字0-9可以直接调用位置参数,规则如下:
| 变量 | 含义 |
|---|---|
| $0 | 脚本本身(文件名) |
| $1 | 第一个位置参数 |
| $n | 第n个位置参数 |
例如脚本文件script.sh
#! /bin/bash
echo "your name is $1"
终端输入:/bin/bash script.sh yexiaowo
终端输出:your name is yexiaowo
还有其他特殊变量:
| 变量 | 含义 |
|---|---|
| $# | 参数个数 |
| $* | 所有参数(以双引号括起来时,所有参数为一整体) |
| $@ | 所有参数 |
| $? | 上个命令的推出状态或函数返回值 |
| $$ | 当前shell进程的ID |
在shell,无论是否有引号,定义的每个变量都被认为是字符串。
shell的字符串可以用单引号,也可以用双引号,也可以不用引号。但各有所区别:
与其他变成语言不同的是,shell中的变量可以直接插入任意位置进行字符串拼接(变量替换),例如:
a="yexiaowo"
b="my name is ${a}"
echo $b
以下的字符串分割命令常用于文件路径处理。
例如先定义一个变量为路径:file="~/dir1/dir2/dir3/a.file.sh",则有:
| 命令 | 作用 | 结果 |
|---|---|---|
| ${file#*/} | 去掉第一个/及左侧的字符串 | dir1/dir2/dir3/a.file.sh |
| ${file##*/} | 去掉最后一个/及左侧的字符串 | a.file.sh |
| ${file%/*} | 去掉最后一个/及右侧的字符串 | ~/dir1/dir2/dir3 |
| ${file%%/*} | 去掉第一个/及右侧的字符串 | ~ |
记忆方法为:键盘上#号在$左边,所以为去左,*号在匹配目标字符串左边,一个#为最小匹配(去掉的最少),两个##为最大匹配,%同理。
还有子串和字符替换
| 命令 | 作用 | 结果 |
|---|---|---|
| ${file:0:5} | 提取第零个字符后的连续5个字符(前5个字符) | ~/dir |
| ${file/i/o} | 将第一个字符i替换为o(后面一个o及/可以为空) | ~/dor1/dir2/dir3/a.file.sh |
| ${file//i/o} | 将所有字符i替换为o(后面一个o及/可以为空) | ~/dor1/dor2/dor3/a.fole.sh |
| ${#file} | 字符串长度 | 25 |
以及针对变量的不同状态赋值
| 命令 | 作用 | 备注 |
|---|---|---|
| ${file-a.file.sh} | 假如 $file 没有设定,则使用 a.file.sh 作传回值 | 空值及非空值时不作处理 |
| ${file:-a.file.sh} | 假如 $file 没有设定或为空值,则使用 a.file.sh 作传回值 | 非空值时不作处理 |
| ${file+a.file.sh} | 假如 $file 设为空值或非空值,均使用 a.file.sht 作传回值 | 没设定时不作处理 |
| ${file:+a.file.sh} | 若 $file 为非空值,则使用 a.file.sh 作传回值 | 没设定及空值时不作处理 |
| ${file=a.file.sh} | 若 $file 没设定,则使用 a.file.sh 作传回值,同时将 $file 赋值为 a.file.sh | 空值及非空值时不作处理 |
| ${file:=a.file.sh} | 若 $file 没设定或为空值,则使用 a.file.sh 作传回值,同时将 $file 赋值为 a.file.sh | 非空值时不作处理 |
| ${file?a.file.sh} | 若 $file 没设定,则将 a.file.sh 输出至 STDERR | 空值及非空值时不作处理 |
| ${file:?a.file.sh} | 若 $file 没设定或为空值,则将 a.file.sh 输出至 STDERR | 非空值时不作处理 |
记忆方法为:+、-号意为是否有;带冒号:意为包含为空值情况;等号=意为同时赋值变量;问号?意为断言是在
shell中的数组用小括号定义,空格分隔。例如:array=(val1 val2 val3)
与shell数组有关的命令有:
| 命令 | 含义 | 结果 |
|---|---|---|
| ${array[*]} | 全部元素 | val1 val2 val3 |
| ${array[@]} | 全部元素 | val1 val2 val3 |
| ${array[0]} | 索引为0的元素 | val1 |
| ${#array[*]} | 元素个数 | 3 |
| ${#array[@]} | 元素个数 | 3 |
| ${#array[0]} | 索引为0的元素的长度 | 4 |
| A[0]=xy | 将索引为0的元素赋值为xy |
注:$array等价于${array[0]}
在bash中,可以使用$()和` `作命令替换,来重组一行命令。即先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
例如:echo today is $(date "+%Y-%m-%d")
输出为:today is 2014-07-01
各自优点:
$()不易与引号混淆,且更直观,且在多层次的复合替换中,不须要额外的跳脱处理(反斜线,反引号需要)例如:
cmd3 $(cmd2 $(cmd1))
cmd3 `cmd2 \`cmd1\``
shell不支持浮点运算(浮点数只能作为字符串)。
运算使用$(())或者$[]进行(此时括号中的$符号可以省略)。
例如:
a=1;b=2;c=3
echo $[a+b*c]
echo $((a<<1))
shell脚本支持几乎所有的数学运算符、关系运算符、逻辑运算符和位操作符(与C++中用法一致)。
$(())和$[]还能计算进制转换,如输出N进制数xx的十进制数可写为(xx也可以是变量):echo$[N#xx]
测试表达式是否成立,若成立返回0,否则返回其他数值。
格式一:test 表达式
格式二:[ 表达式 ] (注:方括号与表达式之间必须用空格隔开)
[ 操作符 文件或目录 ]| 常用操作符 | 说明 | 示例 |
|---|---|---|
| -e filename | 如果filename存在,则为真 | [ -e /var/log/syslog ] |
| -d filename | 如果filename目录存在,则为真 | [ -d /tmp/mydir ] |
| -f filename | 如果filename文件存在,则为真 | [ -f /usr/bin/grep ] |
| -L filename | 如果filename符号链接存在,则为真 | [ -L /usr/bin/grep ] |
| -r filename | 如果filename可读,则为真 | [ -r /var/log/syslog ] |
| -w filename | 如果filename可写,则为真 | [ -w /var/mytmp.txt ] |
| -x filename | 如果filename可执行,则为真 | [ -L /usr/bin/grep ] |
| filename1 -nt filename2 | 如果filename1比filename2新,则为真 | [ /tmp/install/etc/services -nt /etc/services ] |
| filename1 -ot filename2 | 如果filename1比filename2旧,则为真 | [ /tmp/install/etc/services -nt /etc/services ] |
[ 整数1 操作符 整数2 ]| 常用操作符 | 说明 | 示例 |
|---|---|---|
| -eq | 等于(equal) | [ $a -eq 1 ] |
| -ne | 不等于(not equal) | [ $a -ne 1 ] |
| -gt | 大于(greater than) | [ $a -gt 1 ] |
| -lt | 小于(lesser than) | [ $a -lt 1 ] |
| -ge | 大于或等于(greater or equal) | [ $a -ge 1 ] |
| -le | 小于或等于(lesser or equal) | [ $a -le 1 ] |
[ 操作符 字符串 ]| 操作符 | 说明 |
|---|---|
| -z | 字符串内容为空 未定义或者赋予空值的变量将视为空串 |
| -n | 是否有字符串 |
[ 字符串1 操作符 字符串2 ]| 操作符 | 说明 |
|---|---|
| = | 字符串内容相同 |
| != | 字符串内容不同,!表示取反的意思 |
[ 表达式1 ] 操作符 [ 表达式2 ] ...| 操作符 | 说明 |
|---|---|
| -a && |
逻辑与,而且的意思 操作符前后条件都需成立 |
| -o | | |
逻辑或,或者的意思 只需前后操作符中一个成立即可 |
| ! | 逻辑否的意思 |
逻辑测试中还可以使用命令:命令1 操作符 命令2 ...
当&&前的表达式或命令均成立时,才执行&&后的命令和表达式;当||前的表达式或命令均不成立时,才执行||后的命令和表达式。(短路原则)
if 条件测试 ; than
...
elif 条件测试 ; than
...
else
...
...
fi
case 变量 in
情况一变量或值|变量或值|...)
...(cmd)
;;
情况二变量或值|...)
...(cmd)
;;
...
*)# *号意为任意其他
...(cmd)
;;
esac
注:变量或值只能是单个的,之间用|隔开;对于数组变量$array意为数组的第一个值${array[0]}
for 变量 in 串行 ; do
...(cmd)
done
串行:一些字符串的组合,彼此用$IFS所定义的分隔符(如空格符)隔开,这些字符串称为字段
while 条件测试 ; do
...(cmd)
done
until 条件测试 ; do
...
done
read)read命令用于从标准输入读取数值:read 参数 ... 变量名
| read常用参数 | 说明 |
|---|---|
| -a | 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符 |
| -d | 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标准 |
| -p | 后面跟提示信息,即在输入前打印提示信息 |
| -e | 在输入的时候可以使用命令补全功能 |
| -n | 后跟一个数字,定义输入文本的长度,很实用 |
| -r | 屏蔽\,如果没有该选项,则\作为一个转义字符,有的话\就是个正常的字符了 |
| -s | 安静模式,在输入字符时不在屏幕上显示,例如login时输入密码 |
| -l | 后面跟秒数,定义输入字符的等待时间 |
| -u | 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的 |
例如:
#! /bin/bash
read -p "please enter a name." NAME
echo "welcome,$NAME!!!"
原文:https://www.cnblogs.com/yexiaowo/p/shell.html