shell语法
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加号和数字之间有空格
### 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 “Hi\n”,即可输出转义
- 强行不换行:-e后\c,\c可以取消最后的回车(和py中的end = “”相同),因为echo和py中的print相同,最后会自动换行。
- 显示结果到echo “Hello world” > output.txt
- 原样输出字符串,不进行转义或取变量:用单引号引起来
- 显示命令的执行结果:用`引起来
printf语句(c++中是以,隔开每一项,而shell中是以space隔开每一项)
- 格式:printf format-string [arguments…]
- printf “%d\n” 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
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 h3110w0r1d's Blog!