学习笔记|Shell
本文最后更新于:2 years ago
本文在 linux 命令的基础上,具体描述 Shell 脚本的相关知识。
1.shell格式
一堆命令写在在同一个文件里。
注意:第一行 #! 与 shell 之间有空格。
1 |
|
2.执行脚本
source 是 bash shell 的内置命令。(与 . 等价)
1 |
|
3.内建命令
在使用 export PATH=
后,仍能执行的命令就是内建命令。
1 |
|
4.小括号
执行 cd 后,不改变工作目录。
相当于父进程为当前路径,子进程执行该命令。
1 |
|
5.变量
5.1 数据类型
只有一种数据类型:字符串
1 |
|
5.2 变量类型
两种变量:环境变量、本地变量。
环境变量:环境变量存在于所有进程中。环境变量可以从父进程传给子进程,因此 Shell 进程的环境变量可以从当前 Shell 进程传递给 fork 出来的子进程。
1 |
|
本地变量:只存在于当前 Shell 进程中。
注意:等号两边不能有空格,否则会被解释成命令和命令参数。
1 |
|
5.3 变量导出与删除
本地变量只能在当前 Shell 进程中使用,export 可以将本地变量导出为环境变量,使本地变量在其他进程中可以使用。
1 |
|
删除已定义的环境变量和本地变量。
1 |
|
6.通配符
Wildcard
通配符 | 含义 |
---|---|
* | 匹配 0 个或者多个任意字符 |
? | 匹配 1 个任意字符 |
[] | 匹配方括号中任意一个字符 |
通配符与正则表达式的区别
用途不同
通配符用于通配文件名,正则表达式用于匹配文本内容
使用地点不同
通配符通常只能用于shell,被shell自解释。
正则表达式需要被正则引擎解析,需要用于支持正则表达式的代码或命令中。
元字符不同
通配符只有三个元字符,正则表达式根据正则引擎不同会多种多样。
并且相同元字符表示的含义也可能不同。如通配符中表示匹配任意字符,正则中表示前面的字符重复0或任意次。
**实例:**使用 grep是字符串命令,需使用正则表达式;文件名通配使用通配符。
1 |
|
注意
反斜杠(\
)或引号('
, "
)都会使通配符失效。
如: \*
, "*"
, '*'
都表示*
本身,不通配任何文件。
7.命令代换
由反引号括起来的是一条命令,Shell 应先执行该命令,再将执行结果代换到当前命令中。
等号两侧无空格。
1 |
|
命令代换可以使用 $() 表示。
1 |
|
8.算术代换
算术代换要写两个括号或者一个中括号。
1 |
|
PS:二进制的100 + 十进制的3
1 |
|
9.转义字符
连接符:将第一行命令和第二行命令连接起来。
1 |
|
转义符:将特殊字符转义
例如:创建
$ $200.txt
文件。其中 $ 和空格均需要转义。
1 |
|
PS:如何创建和删除
---a.txt
文件?- 方式一:写全路径!
- 方式二:使用 –
1 |
|
10.引号
引号是字符串的界定符。引号中的内容就是纯粹的字符串。
1 |
|
例:想要输出
hello 'hello'
输出单引号使用双引号作为界定符,输出双引号使用单引号作为界定符。
1 |
|
单引号和双引号区别
双引号防止通配符扩展,但是允许变量扩展。
1 |
|
PS:作为好的 Shell 编程习惯,应该总是把变量取值放在双引号内。
11.shell脚本语法
11.1 条件测试 test
$?
:上一个进程退出返回的值。
1 |
|
例1:使用 test 比较大小
参数 | 含义 |
---|---|
-eq | 等于 |
-ne | 不等于 |
-lt | 小于 |
-le | 小于等于 |
-gt | 大于 |
-ge | 大于等于 |
PS:返回 0 表示真,返回 1 表示假。【和其他语言相反】
注意:比较双方只能是整数或者整数变量。
1 |
|
例2:使用 test 判断类型
参数 | 含义 |
---|---|
-d | 是否是目录 |
-f | 是否是普通文件 |
-z | stging 是否为零 |
-n | stging 是否为非零 |
= | 两个字符串是否相同 |
!= | 两个字符串是否不相同 |
1 |
|
例3:使用
[]
代替 test
1 |
|
例4:链接符 -a、-o
1 |
|
11.2 模糊匹配 if
if、then、elif、else、fi 的使用
1 |
|
PS:then
可以分行写,这样 ;
不用写,如下所示。
1 |
|
写成一行
1 |
|
:
是一个特殊的命令
1 |
|
11.3 精准匹配 case
;;
表示语句结束,类似于 C 语言中的break
。【一定别忘了】例:根据输入做 case 判断
1 |
|
实际应用
服务 start、stop、status 等均是通过参数来控制,可以用 case 做脚本进行控制。
1 |
|
11.4 循环 for
类似于 foreach,枚举。
例1:在三种水果中进行枚举。
1 |
|
例2:批量改名
找到所有的 chap1、chap2,更改为 chap1~、chap2~。
1 |
|
11.5 循环 while
count 自减,循环输出 count 值。
1 |
|
11.6 break 与 continue
break:可以指定跳出几层循环。
continue:跳过本次循环,但不会跳出循环。
12.特殊变量与输入输出
特殊变量是由 Shell 自动赋值的。
自动变量 | 含义 |
---|---|
$0 | 相当于 c 中的 argv[0] |
$1、$2… | 相当于 c 中的 argv[1]、argv[2]… |
$# | 参数个数,argc - 1 |
$@ | 表示参数列表 $1、$2、$3、$4… 例如可以使用在 for in 后面 |
$* | 同上 |
$? | 上一条命令的 Exit Status |
$$ | 当前进程号 |
shift 是参数左移出队的操作。
shift 相当于 shift1
shift3:左移出队三个参数
1 |
|
例子:
1 |
|
echo 有两个参数:-e 和 -n
参数 | 含义 |
---|---|
echo | 默认有一个回车 |
-e | 解析转义字符 |
-n | 不换行 |
1 |
|
13.管道
1 |
|
14.tee
将标准输出同时输出到指定的文件中。
1 |
|
15.文件重定向
1 |
|
16.函数
有函数定义,但是没有函数返回值、函数列表。
先定义、再使用。
1 |
|
如何使用参数?
使用 $1、$2、$3…来表示函数的参数。
注意:函数内部使用 $1、$2、$3…只能使用函数的参数。(同时 $#、$@ 也是表示函数的参数列表,而不是整个脚本的参数)
1 |
|
**实例:**批量创建文件夹。
1 |
|
17.调试 shell 脚本
参数 | 含义 |
---|---|
-n | |
-v | |
-x |
18.正则表达式
查找文件中的内容,字符串匹配(grep,egrep)见基础正则和扩展正则区别>。
注意:Linux 中使用,一定要使用双引号。
(1)字符类
字符 | 含义 | 举例 | 说明 |
---|---|---|---|
. | 匹配任意一个字符 | abc. | 匹配 abcd、abc9等 |
[] | 匹配括号中任一字符 | [abc] | 只能匹配a、b、c |
- | 在[]括号内表示字符范围 | [0-9a-fA-F] | 匹配一位十六进制的数字 |
^ | 位于[]括号内的开头,匹配除括号中的字符之外的任意一个字符 | [^xy] | 匹配除 xy 之外的任一字符,可以匹配 a1、b1,但不能匹配 x1、y1 |
[[:xxx:]] | grep 工具预定义的一些命名字符类 | [[:alpha:]] /[[:digit:]] | 匹配一个字母 / 匹配一个数字 |
.
匹配任意一个字符。
1 |
|
[mn]
匹配 [] 里的任意一个字符。
1 |
|
[^yd]
匹配除 [] 中字符的其他任一字符。
1 |
|
\w
【小写w】匹配文字和数字字符,也就是 [A-Za-z0-9]。
1 |
|
\W
【大写W】匹配非文字和数字字符,“\w” 的反置形式。
1 |
|
(2)数量限定符
字符 | 含义 | 举例 | 说明 |
---|---|---|---|
? | 紧跟在它前面的单元应匹配零次或一次 | [0-9]?\.[0-9] | 可匹配 0.0、2.3、.5 |
+ | 紧跟在它前面的单元应匹配一次或多次 | [0-9a-zA-Z_.-]+@[0-9a-zA-Z_.-]+\.com | 匹配邮箱 |
* | 紧跟在它前面的单元应匹配零次或多次 | ||
{N} | 紧跟在它前面的单元应匹配 N 次 | [1-9][0-9]{2} | 匹配100-999的整数 |
{N,} | 紧跟在它前面的单元应匹配至少 N 次 | [1-9][0-9]{2,} | 匹配大于等于100的数 |
{,M} | 紧跟在它前面的单元应匹配最多 M 次 | ||
{N,M} | 紧跟在它前面的单元应匹配至少 N 次,最多 M 次 | [0-9]{1,3}(.[0-9]{1,3}){3} | 匹配 ip,()内重复三次 |
*
*前面的字符可以重复 0 次或者 多次。
1 |
|
x\{m\}
匹配 字符 x重复 m 次 的行。
1 |
|
x\{m,\}
匹配 字符 x 重复 m 次或者 m 次以上 的行。[m, +∞)
1 |
|
x\{m, n\}
匹配 字符 x 重复 m 次或者 m 次以上,不超过 n 次 的行。 [m, n]
1 |
|
(3)位置限定符
字符 | 含义 | 举例 | 说明 |
---|---|---|---|
^ | 匹配行首的位置 | ^Content | 匹配位于一行开头的 Content |
$ | 匹配行末的位置 | answer:$ | 匹配位于一行结尾的 answer: |
\< | 匹配单词开头的位置 | \<ab | 匹配 ab 开头的单词 |
\> | 匹配单词结尾的位置 | ab\> | 匹配 ab 结尾的单词 |
\b | 匹配单词开头或结尾的位置 | 可以完全取代 \< 和 \> | |
\B | 匹配非单词开头和结尾的位置 | \Bab\B | ab 既不在开头,也不在结尾 |
匹配行开头。
1 |
|
匹配行结尾。
1 |
|
匹配单词开头。
1 |
|
匹配单词结尾。
1 |
|
匹配单词。
1 |
|
(4)其他特殊字符
字符 | 含义 | 举例 |
---|---|---|
\ | 转义字符,将特殊字符转义为普通字符;普通字符转义为特殊字符。 | 文本中出现 . 需要使用 \. 来进行转义。普通字符 <> 转义为匹配开头和结尾 \< \> 。 |
() | 将正则表达式一部分括起来组成一个单元,可以对整个单元使用数量限定符。 | [0-9]{1,3}(.[0-9]{1,3}){3} |
| | 连接两个子表达式,表示或的关系。 | n(o|either),匹配 no、neither |
(5)基础正则和扩展正则
egrep 可以直接使用扩展正则。grep 若要使用扩展正,则有两种方式:
将 ?+{}|() 使用 \ 进行转义。
加 -E 参数,grep -E
1 |
|
19.sed
筛选行数据。
19.1 命令格式
sed 参数 ’脚本语句‘ 待操作文件
1 |
|
echo:在 my_shell.sh 中找到 echo
s:表示字符串替换
echo/printf:将 echo 替换成 printf
g:一行出现多次 echo,均全部替换
sed 参数 -f ’脚本文件‘ 待操作的文件
19.2 命令参数
参数 | 含义 |
---|---|
-n | 静默输出,sed 程序在所有脚本指令执行完毕后,自动打印模式空间中的内容。-n屏蔽自动打印。 |
-f | 从文件中读取脚本指令 |
-i | 直接修改源文件。经过脚本指令处理的内容直接输出至源文件。 |
-r | 使用扩展正则。 |
19.3 脚本格式
1 |
|
pattern 是正则表达式,action 是编辑操作。
sed 一行行读取待处理文件,如果某一行与 pattern 匹配,则执行相应的 action
如果一条命令没有 pattern,而只有 action,这个 action 将作用于待处理文件的每一行。
举例:
1 |
|
19.4 脚本参数
参数 | 含义 |
---|---|
a | append 追加 |
i | insert 插入 |
d | delete 删除 |
s | substitution 替换 |
append
在 my_shell.sh 的第 4 行后,追加一行,append_line 在第 5 行显示。
1 |
|
insert
在 my_shell.sh 的第4行,插入一行,insert_line 在第 4 行显示。
1 |
|
delete
注意:替换修改源文件需要加参数 -i。
删除 my_shell.sh 的第 4 行。
1 |
|
删除 my_shell.sh 的第 2 到第 7 行。
1 |
|
substitution
注意:替换修改源文件需要加参数 -i。
将 my_shell.sh 的 echo 替换成 printf。
1 |
|
19.5 替代符
&
在 abc 的两侧加入 ==
。
1 |
|
\1
sed 只支持 basic 正则表达式规范。
匹配两个数字,第一个数字部分用 \1 表示,第二个数字数字用 \2 表示,在 \1 和 \2 位置两侧分别加入 == 和 @@。
1 |
|
19.6 其他
同一个文件,两个替换命令。
1 |
|
同一个文件,两个替换命令。(使用 -e 指定)
1 |
|
**案例:**将 html 的标签删除。
1 |
|
思路:
[^<>]
:匹配任意一个非 <> 的字符。[^<>]*
:确保匹配到 <> 中的一串字符。<[^<>]*>
:强制要求所匹配到的字符串两端需要有 <>。
1 |
|
20.awk
sed:处理行数据
awk:处理列数据
20.1 命令格式
awk 参数 ‘脚本语句’ 待操作文件
1 |
|
awk 参数 -f ‘脚本语句’ 待操作文件
20.2 命令参数
参数 | 含义 |
---|---|
-F: | 指定列的分隔符为 : 。冒号可以换成其他符号。 |
-F
在 /etc/passwd 中,以 :
分割每一列。
1 |
|
20.3 脚本格式
1 |
|
**例:**有以下三行数据,筛选大于等于 50 的行。
1 |
|
1 |
|
20.4 使用变量
**例:**统计文本的空行数。
1 |
|
/^ *$/
:匹配空格开头,空格重复零次或多次,并以此结尾。{count=count+1}
:使用 count 进行计数。END
:匹配结束进行打印。
**例:**统计 id 在 [2600, 2700) 的行数。
1 |
|
补充:
END 是在匹配最后进行操作。
BEGIN 是在匹配之前进行操作。
在匹配之前,对文本进行拆分。(以:
为分割进行拆分)
FS 是内建变量,实际上是宏。表示分隔符,缺省是来纳许的空格和 tab。
1 |
|
21.C语言使用正则
编译正则表达式 regcomp()
匹配正则表达式 regexec()
释放正则表达式 regfree()