Shell 语言的基础语法,包括基础知识(变量、打印、运算符)、流程控制(分支、循环)和模块化(函数封装、文件封装、参数传递)三个部分。
本篇文章是 Shell脚本基础 的增强版。
一、基础知识
1.1 变量
变量定义
1 | # 使用变量,建议方式 |
变量赋值
1 | # 除了显式赋值,也可以将命令的结果存入到变量,如下就是将`ls /etc`的结果存到到了file_array |
数组变量
1 | # 数组的定义 |
1.2 打印
echo
Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。命令格式:
1 | echo string |
显示普通字符串:
echo "It is a test"
这里的双引号完全可以省略(echo It is a test)
显示转义字符
echo "\"It is a test\""
结果将是:”It is a test”,同样双引号也可以省略
显示变量
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量1
2
3
4
5
6
7!/bin/sh
read name
echo "$name It is a test"
以上代码保存为 test.sh, name 接收标准输入的变量,结果将是:
[root@www ~]# sh test.sh
OK #标准输入
OK It is a test #输出显示换行
echo -e "OK! \n" # -e 开启转义echo "It is a test"
输出结果:
OK! It is a test
显示不换行
#!/bin/sh echo -e "OK! \c" # -e 开启转义 \c 不换行 echo "It is a test"
输出结果:
OK! It is a test
显示结果定向至文件
echo "It is a test" > myfile
原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
输出结果:$name"
显示命令执行结果(这里因为无法打印出原字符所以加了转义符,实际不需要转义)
echo
date``,注意: 这里使用的是反引号`,而不是单引号’。结束时显示日期:Thu Jul 24 10:08:46 CST 2014
printf
printf 命令模仿 C 程序库(library)里的 printf() 程序。printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。
printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。
语法:
1 | printf format-string [arguments...] |
printf 转义序列:
序列 | 说明 |
---|---|
\a | 警告字符,通常为 ASCII 的 BEL 字符 |
\b | 后退 |
\c | 抑制(不显示)输出结果中任何结尾的换行字符(只在 %b 格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 |
\f | 换页(formfeed) |
\n | 换行 |
\r | 回车(Carriage return) |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 一个字面上的反斜杠字符 |
\ddd | 表示 1 到 3 位数八进制值的字符。仅在格式字符串中有效 |
\0ddd | 表示 1 到 3 位的八进制值字符 |
1.3 运算符
算数运算符
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | expr $a + $b 结果为 30。 |
- | 减法 | expr $a - $b 结果为 -10。 |
* | 乘法 | expr $a * $b 结果为 200。 |
/ | 除法 | expr $b / $a 结果为 2。 |
% | 取余 | expr $b % $a 结果为 0。 |
= | 赋值 | a=$b 把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ b ] 返回 true。 |
关系运算符
关系运算符只用于比较数字之间的关系,不支持字符串,除非字符串的值是数字
假定 a =10, b = 20
运算符 | 说明 | 举例 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | 检测两个数是否不相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
布尔运算符
假定 a =10, b = 20
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
逻辑运算符
假定 a =10, b = 20
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
注意需要两个嵌套的中括号
字符串运算符
假定 var1=”abc”,var2=”efg”
运算符 | 说明 | 举例 |
---|---|---|
= | 检测字符串相等返回 true | [ $var1 = $var2 ] 返回 false |
!= | 检测字符串不相等返回 true | [ $var1 != $var2 ] 返回 true |
-z | 检测字符串长度为 0 返回 true | [ -z $var1 ] 返回 false |
-n | 检测字符串长度不为 0 返回 true | [ -n $var1 ] 返回 true |
${} | 检测字符串不为空返回 true | [ $var1 ] 返回 true |
文件测试运算符
使用方法:-
操作符 | 说明 |
---|---|
-e | 检测文件是否存在 |
-d | 检测目录是否存在 |
-f | 普通文件检测(既不是目录,也不是设备文件) |
-r | 文件可读检测 |
-w | 文件可写检测 |
-x | 文件可执行检测 |
-b | 块设备检测 |
-c | 字符设备检测 |
-p | 有名管道检测 |
-s | 文件大小是否为 0 |
-S | 文件是否是 socket 连接 |
-L | 文件是否存在并且是一个符号链接 |
-g | 文件 SGID 位检测 |
-u | 文件 SUID 位检测 |
-k | 文件粘滞位(Sticky Bit)检测 |
二、流程控制
2.1 分支
if-else
1 | if |
分支注意事项:
- condition 的表示
- if else 的 […] 判断语句中大于使用 -gt,小于使用 -lt(数值)
- 如果使用 ((…)) 作为判断语句,大于和小于可以直接使用 > 和 <。
case … esac
case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用 两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。
1 | case 值 in |
如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令
示例:
1 | echo '输入 1 到 4 之间的数字:' |
2.2 循环
循环包括 for 循环、while 循环、无限循环和 util 循环。
for 循环
1 | for var in item1 item2 ... itemN |
while 循环
1 | while condition |
无限循环
1 | 1 |
until 循环
1 | until condition |
三、模块化
3.1 函数封装
函数格式:
1 | [ function ] funname [()] |
说明:
- 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数
- 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n(范围:0-255)
3.2 文件封装
可以将某一部分内容放到一个文件里,作为一个更大的模块的封装。注意在调用该文件执行的时候,是启动了一个子 shell 来对文件进行解释操作的。
3.3 内容传递
模块之间的交互主要可以通过管道,参数,文件传递等方式
管道
管道方式是在调用多个函数的时候,将前一个命令的输出作为下一个命令的输入。管道传递的内容需要后一个命令具有解析输入的功能,一般后一个命令是 Linux 自带的命令。
参数
参数是在函数调用时可能用到的,用于不同模块内容的交互(参入主要是传入模块内容)
参数访问:
在函数体内部,通过 $n 的形式来获取参数的值,例如, $1 表示第一个参数,$2 表示第二个参数…
示例:
1 | !/bin/bash |
参数处理:
使用 for 循环,遍历所有的参数,设置相应的标志位
1 | # 对所有的参数预处理,得到参数标志 |
参数表示:(对外)
在对外展示 shell 脚本可以处理的参数的时候,需要对可选项等作出表示,shell 命令使用不同的括号来表示不同类型的参数
- []:内容可写可不写
- {}:必须要从{}中选择一个参数
- <>:必选
特殊参数字符:
参数处理 | 说明 |
---|---|
$# | 传递到脚本或函数的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程 ID 号 |
$! | 后台运行的最后一个进程的 ID 号 |
$@ | 与 $* 相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示 Shell 使用的当前选项,与 set 命令功能相同。 |
$? | 显示最后命令的退出状态。0 表示没有错误,其他任何值表明有错误。 |
文件传递
文件传递方式是将某些文本内容写入到文件,然后另一个命令或者模块利用该文件进行进一步的操作。
文件的用法:
- 传递内容——写入到文件内容并由另一个模块或者命令读取
- 设标志位——作为一个同步标志,控制运行流程
参考
【1】Shell 教程
【2】括号中的可选、必选表示
原文链接: https://www.delta1037.cn/2025/Linux/Shell基础语法/
版权声明: 转载请注明出处.