前言
学习 Shell 语言的一些笔记。
Shell 是一种命令行语言,也可以作为一种脚本语言,Linux 中的命令行窗口就是 Shell 的界面,所以有必要稍微了解一些 Shell 的基本语法。
基本语法
1 | !/bin/bash |
疑难解答
- 传参时因为有特殊符号所以报错,如
python .\markdown_editor.py --title -p 929_独特的电子邮件地址(简单).md
中的括号- 给参数加上引号强制其为字符串即可
python .\markdown_editor.py --title -p "929_独特的电子邮件地址(简单).md"
- 给参数加上引号强制其为字符串即可
基本数据类型
注释
- 单行注释:
#
开头
输出
echo
+ 输出内容- 一行写不下使用
\
换行继续写 - 换行
echo -e abc\n
,-e
表示使用转义 - 末尾不换行
echo -e abc\c
- 显示日期
echo `date`
- 还可以用
printf
类似 C 语言printf "%d - %d = $a\n" 12 123 #输出12 - 123 = 1231
重定向
命令 | 说明 |
---|---|
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 之间的内容作为输入 |
默认文件描述符:0 - 标准输入文件(stdin), 1 - 标准输出文件(stdout), 2 - 标准错误文件(stderr)
屏蔽输出:
1 | command > /dev/null # 屏蔽输出 |
/dev/null
是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是
/dev/null
文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
变量
- 变量的定义:
a=1
,b="xyz"
很基础的赋值语句即可,注意:等号中间不要加空格 - 使用变量: 前面使用
$
符号如${a}
,$b
均可,大括号不是必须的,但建议都加上 - 只读变量:
readonly a
- 删除变量:
unset a
字符串
- 定义: 例如
a='string'
,可以是单引号、双引号、没有引号,但单引号是“绝对”字符串,不能使用变量和转义符 - 字符串拼接:直接连在一起写即可,
string${a}"string2"
- 获取字符串长度:
${#a}
- 字符串截取:
${a:0:4}
表示截取索引 0 开始的 4 个字符 - 运算(下面均返回布尔值)
=
比较运算[ $a = $b ]
!=
-z
长度为 0 返回true
,[ -z $a ]
-n
长度不为 0,[ -n $a ]
$
字符串不为空,[ $a ]
数组
- 定义:
a=(x1 x2 x3 x4)
- 赋值:
a[0]=x5
- 取值:
${a[0]}
, 取所有元素${s[@]}
, 对数组${a}
等价于${a[0]}
- 获取长度:
${#a[@]}
或${#a[*]}
基本运算符
- 算术运算符:
+-/%
, 乘法\*
, 赋值=
, 相等==
, 不等!=
.- 不能直接运行,需要使用命令
expr
, 例如expr 1 + 1
- 运算符与值之间要有空格,例如
expr 1 + 1
. - 如果要获取运算结果的话要用反引号
`
包围运算表达式,例如d=`expr 1 + 1`
- 条件表达式之间也要空格
[ $a == $b ]
- 不能直接运行,需要使用命令
- 关系运算符:
-eq
,-ne
,-gt
(大于),-lt
,-ge
,-le
(小于等于) - 布尔运算:
!
(非),-o
(或),-a
(与) - 逻辑运算:
&&
(逻辑与),||
(逻辑或)
注:逻辑运算要加双层中括号
1 | 布尔运算 |
文件运算符
操作符 | 说明 | 举例 |
---|---|---|
-b file |
检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回
false |
-c file |
检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回
false |
-d file |
检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回
false |
-f file |
检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true |
-g file |
检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回
false |
-k file |
检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回
false |
-p file |
检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回
false |
-u file |
检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回
false |
-r file |
检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true |
-w file |
检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true |
-x file |
检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true |
-s file |
检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true |
-e fil e |
检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true |
流程控制
基本的流程控制有三种:循环、条件、顺序
条件语句
if语句
if else fi
的使用方法如下
1 | if condition1 |
可以写成一行,用分号分隔开
1 | if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi |
因为逻辑运算比较麻烦,所以可以使用 ((comdition))
简化运算,双括号内的条件类似 C 语言不再有空格限制
1 | a=10 |
case语句
case ... esac
类似 switch ... case
语句
1 | case 值 in |
;;
类似于 break
循环语句
for循环
1 | for var in item1 item2 ... itemN |
同样可以使用双括号简化
1 | for((index=0; index < 6; index++)) |
while循环
1 | while condition |
同样可以使用双括号简化
1 | int=1 |
until循环
类似与其他语言中的 do...while
循环,
1 | until condition |
控制语句
break
, continue
与其他语言的没什么变化
1 | while : |
退出
想要提前退出不执行后续代码
1 | exit 1 |
命令行参数
可以在运行脚本的时候传递参数,例如
bash example.sh a b c
那么如何获取传递的参数呢?其实很类似变量的使用,即
$1 $2 $3
, 还有 $0
表示含路径的文件名
参数处理 | 说明 |
---|---|
$# |
传递到脚本的参数个数 |
$* |
以一个单字符串显示所有向脚本传递的参数。
如"$*" 用「"」括起来的情况、以"$1 $2 … $n" 的形式输出所有参数。 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一个进程的ID号 |
$@ |
与$* 相同,但是使用时加引号,并在引号中返回每个参数。
如"$@" 用「"」括起来的情况、以"$1" "$2" … "$n"
的形式输出所有参数。 |
$? |
显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
差不多了,毕竟只是写写简单的脚本,再复杂一些的内容可以通过 Python, C++ 等语言完成,就到此为止吧,后面有遇到什么问题的话再补充