shell语法
一门新的语言
Linux中常见的脚本
sh:/usr/bin/sh或/bin/sh
bash:/bin/bash
csh:/usr/bin/csh
ksh:/usr/bin/ksh
zsh
开头必须使用 #! /bin/bash指名bash为脚本解释器
运行方式:
作为可执行文件:
chmod x test.sh使脚本具有可执行权限
./test.sh当前路径下执行(相对路径)
/home/acs/test.sh绝对路径下执行
~/test.sh家目录下执行
用解释器执行
bash test.sh
echo
意思和c 中cout 或 printf相同
注释
井号后面的都是注释,(与py相同)
其实脚本解释的时候#! /bin/bash解释的时候也是注释,只是系统识别为脚本解释器
多行注释:前 :<<EOF后:EOF;其中EOF也可以换成其他字符串,或者符号(必须首位相同)
变量
变量的定义
定义变量不需要¥符号
name1=’yxc’ (单引号定于字符串)
name2=”yxc” (双引号定义字符串)
name3=yxc (可以不加引号,同样表示字符串)
注意等号两边不能有空格!!!否则会报错
使用变量
使用变量需要加上¥(此符号在bash中意为取值),或者$(),花括号是可选的,主要是为了帮助解释器识别边界
echo $yxc
echo $(yxc)
echo会自动换行
错误:echo $namesacwing,因为没有括号,边界判断不对,不知道是namesacwing还是names
只读变量
readonly 变量(相当于c 中的const,声明了一个只读变量)
declare -r 变量
删除变量
unset(类似于c 终端undef),如果一个变量被删除,后面调用的时候会替换为空(NULL)
变量类型
自定义变量(局部变量):子进程不能访问的变量
环境变量(全局变量):子进程可以访问的变量
自定义变量转环境变量
export 变量名
declare -x 变量名
此时可以在子进程中使用变量
使用bash
使用bash会将原进程bash睡眠掉,进入一个新的bash子进程
退出:exit或者ctrl d
环境变量转自定义变量
declare x 变量名(可以理解为给变量赋予了自定义权限)
字符串
字符串可以使用单引号,也可以使用双引号,也可以不使用引号
单引号和双引号的区别(不加引号和双引号相同)
单引号中的内容会原样输出,不会执行,不会取变量(即不会转义),即没有使用&符号取值
双引号中的内容可以执行,可以取变量,即可以使用&取值
取出字符串的长度
¥后面加井号
echo ${井号name},即可以取出name的长度(注意这个地方是花括号)
提取子串
根据下标取值
echo ${name:m:n}注意这个每一个下标前都有冒号
查看自己开了多少进程
top可以查看
按下退出
文件参数变量
在执行shell脚本时可以想脚本传递参数,$1时第一个参数,$2是第二个参数…,特殊的是$0是文件名(包含路径)
$#:文件传入参数的个数(不包括文件名)
$*:由所有参数构成的用空格隔开的字符串,整体为字符串用双引号括起来
$@:每个参数分别用双引号括起来的字符串(@和*都是取所有的意思)
$$:脚本当前运行的进程ID
$?:上一条命令的退出状态(注意不是stdout,而是exit code),0表示正常退出,其他值表示错误
$(command):返回command这条命令的stdout(注意区分stdout和exit code,输出的数是stdout,例如cout,而退出状态是exit code,例如c 中的return)
command
返回command这条命令的stdout,(~上面的`)(7,8等价)
$()小括号是获取stdout的值,${}是取变量的值
数组
数组中可以存放多个不同的值,只支持一位数组,初始化时不需要指定数组大小(和py中的list一样不需要指定数组大小)
定义
数组用小括号表示,元素之间用空格隔开,如:array=(1 abc “def” yxc)
也可以直接定义数组中某个元素的值,如:array[0]=1,array[1]=abc,array[2]=”def”
读取数组中某个元素的值
格式:${array[index]}
echo ${array[0]}
读取整个数组
格式:(@和*都是取所有的意思)
$(array[@])
$(array[*])
expr命令
格式:expr 表达式 ####说明:
用空格隔开每一项
用反斜杠放在shell特定的字符前面,发现表达式运行错误时,可以试试转义
包含空格和其他特殊字符的字符串要用引号括起来
expr会在stdout中输出结果,如果结果为真,stdout为1,否则为0
expr也有exit code返回值,如果为真,exit code为0,否则为1
stdout 和 exit code 返回值为互反(真时相反,假时也相反)
字符串表达式(以下参数都是在expr后面的)
输出长度:length STRING:返回STRING的长度
index STRING CHARSET:CHARSET中任意单个字符在STRING中最前面的字符位置,下标从1开始。如果子啊STRING中完全不存在CHARSET中的字符,则返回0
substr STRING POSITION LENGTH 返回STRING字符串中从POSITON开始,长度最大为LENGTH的子串。如果POSITION或LENGTH为负数,0或非数值,则返回空字符串(下标从1开始)
整数表达式
expr支持普通算数操作,算数表达式优先级低于字符串表达式,高于逻辑表达式
- — 加减运算,两端参数会转化为整数,如果转化失败则会报错
* / % 乘除取余运算,两端参数会转化为整数(*在shell中有特殊含义,所以需要转义)
()可以表示优先级,但是需要用反斜杠转义
逻辑表达式
| 或(c 中是||,少一半):如果第一个值不是0,则会返回第一个值,第二个值不会计算,如果第一个参数非空并且非0,则会返回第一个参数的值
& 与 (c 中是&&,少一半):如果第一个值是0,则不会计算第二个值(短路特性),如果都非空并且非0,则会返回第一个值
== 与 = 是同义词,但是还是要按照c 来写逻辑等号==,复制=
< <= > >= != == = 比较两端的参数,如果为true则返回1,否则返回0,expr首先尝试将两端的参数转换为整数,并做算数比较,如果转换失败,则按字符集排序规则做字符比较(strcmp)
需要转义的:*、()、>、<=、|、&
echo expr a b加号和数字之间有空格
代码语言:javascript复制 ### read命令(cin或scanf)
用于从标准输入中读入单行数据,当读到文件结束符时,exit code为1,否则为0
-p 添加提示信息(类似于input(提示信息))
-t 后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令
echo命令(相当于cout或printf)
输出格式:echo STRING
显示普通字符串:echo “Hello acterminal”,引号也可以省略
显示转义字符:echo “"Hello acterminal"“注意只能使用双引号,单引号不能够转义
也可以省略最外面表示字符串的双引号:echo "Hello acterminal"
显示变量:注意一定要用双引号,单引号不能够转义:name=yxc echo “My name is $name”
显示换行:直接n无法显示换行转义,开启转义需要-e:例如:echo -e “Hin”,即可输出转义
强行不换行:-e后c,c可以取消最后的回车(和py中的end = “”相同),因为echo和py中的print相同,最后会自动换行。
显示结果到echo “Hello world” > output.txt
原样输出字符串,不进行转义或取变量:用单引号引起来
显示命令的执行结果:用`引起来
printf语句(c 中是以,隔开每一项,而shell中是以space隔开每一项)
格式:printf format-string [arguments…]
printf “%dn” yxc
shell中printf不自带换行,所以需要自己加上n(此时无需-e进行转义)
文件逻辑运算符
|与&单与和单或是expr中的(必须在expr中使用)
而||与&&双与和双或是bash中自带的,可以直接在bash中使用
也带有短路特性
表达式中的exit code为0表示真,非0表示假
可以根据短路特性来做if表达式
test命令
test命令用于判断文件类型,以及对变量做比较
test命令用exit code来返回结果,而不是使用stdout,0表示真,非0表示假
test -e test.sh && echo “exist” || echo “Not exist”这种情况,如果前面test判断为0(真就会执行逻辑与(虽然是0,但是也是真,这种情况下可以不去看是0还是1,直接根据真假判断))
文件类型判断
-e文件是否存在(exist)
-f是否为文件(file)
-d是否为目录(directory)
文件权限判断
-r文件是否可读
-w文件是否可写
-x文件是否可执行
-s文件是否为非空文件,是则返回0(真),否则返回1(假)
整数间的比较
-eq a是否等于b(equal)(为什么不是-e,因为-e是转义,已经被使用过,-e也可以是exist中的是否存在)
-ne a是否不等于b(not equal)
-gt a是否大于b(great test)
-lt a是否小于b(less test)
-ge a是否大于等于b(great or equal)
-le a是否小于等于b (less or equal)
注意区分expr和test
expr是stdout,1表示真,0表示假(就和if一样,if内部是1即为真)
test是exit code,0表示真,非0表示假(就和return一样,return 0即为真,return 一个非0的值即为假)
字符串比较
-z判断STRING是否为空,如果为空则返回true
-n判断STRING是否为非空,如果为非空则返回true(-n也可以省略)
== 判断s1和s2是否相等
!=判断s1和s2是否不相等
>和<判断(需要用反斜杠转义),结果等于使用strcmp(逐个字符的ascii码进行比较)
多重条件判定
命令格式:test -r filename -a -x filename(由2,3条来链接两个test命令,第二个命令不需要test)
-a:&&,and
-o:||,or
!:例如test ! -x filename:当filename不可执行时,返回true
判断符号
【】和test用法几乎一样,更常用于if语句中
[]内的每一项都要用空格隔开
中括号内的变量,最好用双引号括起来(为了防止当变量中有空格时&取值出现错误(too many arguments))
中括号内的常熟,最好用单或双引号括起来
判断语句
if then语句,(类似与c 中的if-else语句)if后面跟的是命令,不是值
if expr 3 < 3
和if 0相同,但是0不是命令,所以无法执行
需要写if后面跟着命令 if expr 3 < 3
if then elif then else fi
case $变量 in 值1)…;;值2)…;;*)…;; esac