shell 是一个命令行解释器,它接收应用程序/ 用户命令,然后调用操作系统内核。Shell 还是一个功能的强大的编程语言,易编写、易调式、灵活性强。
- Linux 提供的 Shell 解析器有:

- bash 和 sh 的关系

- CentOS 默认的解析器是 bash
Shell 脚本入门:
- 脚本文件格式:一般文件都以 .sh 结尾。当然不加后缀,只要文件里面的内容符合 shell 的格式,那么都是可以执行的。只是 .sh 是约定俗成的一种规定。
- 脚本格式:脚本都要以
#!bin/bash开头,这是为了指定解析器。 - hello world:
- 创建一个 shell 脚本文件
- 编辑文件,在文件中写出hello
echo "hello, world" - 保存并退出
- 脚本的常用执行方式:
- 采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)
- 采用输入脚本的绝对路径或相对路径(必须具有可执行权限+x)
chmod +x 脚本路径。添加好可执行权限以后,可以直接输入脚本路径,直接执行(不需要在输入 bash 或者 sh) - 在脚本路径前加上
source 或 .也可以执行前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束的时候,则子 shell 关闭,回到 shell 中。 第三种则是不打开子 shell,直接在当前的 shell 中直接执行。这样的执行方式,区别在于某些变量的作用域不同,有可能在子 shell 里面进行了更改,但最后在最外层的 shell 中没有效果。这也就是在我们修改完
/etc/profile后需要 source 一下的原因。
变量:
系统预定义变量:
- 常用的系统变量:
- $HOME
- $PED
- $SHELL
- $USER
- …
- 查看系统变得值

- 显示当前 Shell 中的所有变量:
set
自定义变量:
- 基本语法:
- 定义变量:
变量名=变量值=号后面不能有空格 - 撤销变量:
unset 变量名 - 声明静态变量:
readonly 变量名=变量值静态变量不能 unset
- 定义变量:
- 变量定义规则:
- 变量名称可以由:字母、数字、下划线组成,但是不能以数字开头。环境变量建议全部大写。
- =等号两侧不能有空格
- 变量的值如果有空格,需要使用双引号或者单引号括起来
- 在 bash 中,变量默认都是字符串类型,无法直接进行数值运算
- 全局变量:
- 先声明一个局部变量
export 局部变量就变成了全局变量。在子 shell 中修改全局变量是不会影响到外部的 shell 的。
特殊变量:
$n:
$n 其中 n 为数字,$0 代表该脚本名称,$1 - $9 代表第一到第九个参数,十以上的参数需要用到大括号 ${10}
[root@CentOS-Study script]# touch parameter.sh[root@CentOS-Study script]#[root@CentOS-Study script]# vim parameter.sh#!/bin/bashecho '===================$n==============='echo $0echo $1echo $2[root@CentOS-Study script]#[root@CentOS-Study script]# chmod 777 parameter.sh[root@CentOS-Study script]# ./parameter.sh cls xz===================$n===============./parameter.shclsxz[root@CentOS-Study script]#
$#:
$# 获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强交办的健壮性。
[root@CentOS-Study script]# vim parameter.sh#!/bin/bashecho '===================$n==============='echo $0echo $1echo $2echo '===================$#==============='echo $#[root@CentOS-Study script]#[root@CentOS-Study script]# ./parameter.sh cls xz===================$n===============./parameter.shclsxz===================$#===============2[root@CentOS-Study script]#
$* 和 $@:
- $ 这个变量代表命令行中所有的参数,$ 把所有的参数看成一个整体。
- $@ 这个变量也代表命令行中的所有参数,但 $@ 把每个参数区别对待。 ```shell [root@CentOS-Study script]# vim parameter.sh
!/bin/bash
echo ‘===================$n===============’ echo $0 echo $1 echo $2 echo ‘===================$#===============’ echo $# echo ‘===================$===============’ echo $ echo ‘===================$@===============’ echo $@
[root@CentOS-Study script]# [root@CentOS-Study script]# ./parameter.sh a b c d e f g ===================$n=============== ./parameter.sh a b ===================$#=============== 7 ===================$*=============== a b c d e f g ===================$@=============== a b c d e f g [root@CentOS-Study script]#
---<a name="yPdZK"></a>### $?:$? 最后一次执行的命令返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量值非0(具体哪个数字由自己决定),则证明上一个命令执行不正确。```shell[root@CentOS-Study script]# ./parameter.sh a b c d e f g===================$n===============./parameter.shab===================$#===============7===================$*===============a b c d e f g===================$@===============a b c d e f g[root@CentOS-Study script]# echo $?0[root@CentOS-Study script]#[root@CentOS-Study script]#[root@CentOS-Study script]# parameter.shbash: parameter.sh: command not found...[root@CentOS-Study script]# echo $?127[root@CentOS-Study script]#
运算符:
基本语法:$((运算式))或$[运算式]
[root@CentOS-Study script]# touch computing.sh[root@CentOS-Study script]# vim computing.sh#!/bin/bashecho '================computing=================='echo $(($1+$2))echo $[$1-$2]echo $[($1+$2)*4][root@CentOS-Study script]# chmod 777 computing.sh[root@CentOS-Study script]# ./computing.sh 5 6================Count==================11-144[root@CentOS-Study script]#
条件判断:
- 基本语法:
test condition条件表达式[ condition条件表达式 ]condition 前后都要有空格’
条件非空即为 true,[XXXX] 返回 true/ 0,[ ] 返回 false/ 1
- 常用判断条件:
- 两个整数之间比较
- -eq:等于 equal
- -ne:不等于 no equal
- -lt:小于 less than
- -le:小于等于 less equal
- -gt:大于 greater than
- -ge:大于等于 greater equal
- 两个整数之间比较
字符串之间的比较,用等号 “=” 判断相等;用 “!=” 判断不等。
- 按照文件权限进行判断:
- -r:有读的权限 read
- -w:有写的权限 write
- -x:有执行的权限 execute
- 按照文件类型进行判断:
- -e:文件存在 existence
- -f:文件存在且是一个常规的文件 file
- -d:文件存在且是一个目录 directory
- 多条件判断:
- &&:表示前一条指令执行成功,才会执行下一条指令
- ||:表示上一条命令执行失败,才执行下一条命令 ```shell [root@CentOS-Study script]# touch test [root@CentOS-Study script]# ll total 8 -rwxrwxrwx. 1 root root 109 Jun 13 21:28 computing.sh -rwxrwxrwx. 1 root root 236 Jun 13 21:18 parameter.sh -rw-r—r—. 1 root root 0 Jun 13 21:46 test [root@CentOS-Study script]# [root@CentOS-Study script]# [root@CentOS-Study script]# [ -r test ] [root@CentOS-Study script]# echo $? 0 [root@CentOS-Study script]# [root@CentOS-Study script]# [root@CentOS-Study script]# [ -x test ] [root@CentOS-Study script]# echo $? 1 [root@CentOS-Study script]# [ ] [root@CentOS-Study script]# echo $? 1 [root@CentOS-Study script]# [ abc ] [root@CentOS-Study script]# echo $? 0 [root@CentOS-Study script]# [root@CentOS-Study script]# [ abc ] && echo OK || echo not OK OK [root@CentOS-Study script]# [ ] && echo OK || echo not OK not OK [root@CentOS-Study script]#
---<a name="xdkJD"></a># 流程控制:<a name="EinFc"></a>## if 判断:1. 基本语法:1. 单分支:```shell#!/bin/bashif [ condition ]; then程序fi# =============或者=============if [ condition ]then程序fi
if [ condition ]; then 程序-1 elif [ condition ]; then 程序-2 elif [ condition ]; then 程序-3 else 程序-4 fi
注意事项:1. [ condition ] condition表达式前后都要有空格1. if 后面要有空格---<a name="fV1m7"></a>## case 语句:基本用法:```shell#!/bin/bashcase $变量名 in"值1")程序-1;;"值2")程序-2;;"值3")程序-3;;"值....")....;;*)上述都匹配不上,最终执行的程序;;esac
- case 行尾必须为单词 “in”,每一个模式匹配必须以右括号 “)” 结束
- 双分号 “;;” 表示命令序列结束,相当于 java 中的 break
- 最后的 “*)” 表示默认模式,相当于 java 中的 default
for 循环:
for (( i=1; i <= $1; i++ )) do sum = $[ $sum + $i ] done echo $sum
2. 基本语法 2:```shell#!/bin/bashfor 变量 in 值1 值2 值3 ...do程序done--------------------------------------------------------------------------[root@CentOS-Study script]# touch parameter_for_test.sh[root@CentOS-Study script]# vim parameter_for_test.sh#!/bin/bashecho '===========$*================'for par in "$*"doecho $pardoneecho '===========$@================'for par in "$@"doecho $pardone[root@CentOS-Study script]# chmod +x parameter_for_test.sh[root@CentOS-Study script]# ./parameter_for_test.sh a b c d===========$*================a b c d===========$@================abcd[root@CentOS-Study script]#
while 循环:
基本用法:
[root@CentOS-Study script]# touch parameter_while_test.sh[root@CentOS-Study script]# vim parameter_while_test.sh#!/bin/bashsum=0i=1while [ $i -le 100 ]dosum=$[$sum+$i]i=$[$i+1]doneecho $sum[root@CentOS-Study script]#[root@CentOS-Study script]# chmod +x parameter_while_test.sh[root@CentOS-Study script]# ./parameter_while_test.sh5050[root@CentOS-Study script]#
read 读取控制台输入
基本用法:read [选项] [参数]
- 选项:
- -p:指定读取值时的提示符
- -t:指定读取值时等待的时间(秒),如果不加 -t 则表示一直等待
- 参数:
- 变量:指定读取值的变量名 ```shell [root@CentOS-Study script]# touch read_test.sh [root@CentOS-Study script]# vim read_test.sh
!/bin/bash
read -t 10 -p “please type your words: “ word echo “you wrote: $word”
[root@CentOS-Study script]# [root@CentOS-Study script]# chmod +x read_test.sh [root@CentOS-Study script]# [root@CentOS-Study script]# [root@CentOS-Study script]# ./read_test.sh please type your word: sabcd you wrote: abcd [root@CentOS-Study script]#
---<a name="JHJHa"></a># 函数:<a name="U4tBO"></a>## 系统函数:<a name="ZZI9T"></a>### basename:基本用法:`basename [string/ pathname] [suffix]`basename 命令会删掉所有的前缀包括最后一个 "/" 字符,然后将字符串显示出来。<br />其中 suffix 为后缀,如果 suffix 被置顶了,basename 会将 pathname 或者 string 中的 suffix 去掉```shell[root@CentOS-Study script]#[root@CentOS-Study script]# pwd/root/script[root@CentOS-Study script]#[root@CentOS-Study script]# lscomputing.sh parameter_for_test.sh parameter.sh parameter_while_test.sh read_test.sh test[root@CentOS-Study script]#[root@CentOS-Study script]#[root@CentOS-Study script]# basename /root/script/read_test.shread_test.sh[root@CentOS-Study script]#[root@CentOS-Study script]# basename /root/script/read_test.sh .shread_test[root@CentOS-Study script]#
dirname:
基本用法:dirname 文件绝对路径从给定的包含绝对路径的文件名中去除文件名(非目录部分),然后返回剩下的路径。
dirname 可以理解为取文件路径的绝对路径
[root@CentOS-Study script]# dirname /root/script/read_test.sh/root/script[root@CentOS-Study script]#[root@CentOS-Study script]# dirname ./read_test.sh.[root@CentOS-Study script]#
自定义函数:
基本用法:
[ function ] funname[()]{Action;[return int;]}
- 必须在调用函数的地方之前,先声明函数,shell 脚本是逐行运行,不悔向其他语言一样先编译。
- 函数返回值,只能通过 $? 系统变量获取,可以显示加 “return” 返回,如果不加,将一最后一条命令运行结果作为返回值。return 后跟数值(0-255)
[root@CentOS-Study script]# touch fun_test.sh[root@CentOS-Study script]# vim fun_test.sh#!/bin/bashfunction sum(){s=0s=$[$1+$2]echo $s}read -p "the first number: " aread -p "the second number: " bresult=$(sum $a $b)echo $result[root@CentOS-Study script]# chmod +x fun_test.sh[root@CentOS-Study script]# ./fun_test.shthe first number: 5the second number: 38[root@CentOS-Study script]#
正则表达式:
正则表达式使用单个字符串来描述,匹配一系列符合某个语法规则的字符串。在很多文本编辑器中,正则表达式通常用来检索,替换那些符合某个模式的文本。在 Linux 中,grep,sed ,awk 等文本处理工具都支持通过正则进行匹配。
常规匹配:
遗传不包含特殊字符的正表达式匹配他自己,他只会匹配包含自身的选项:
常用特殊字符:
字符 ^:
^ 匹配一行的开头,会匹配出所有以 a 开头的行
字符 $:
$ 匹配一行的结束,会匹配出所有以 t 结尾的行:
字符 .:
. 匹配任意一个字符,会匹配包含 r..b 形式的所有行
字符 *:
*不单独使用,一般和上一个字符连用,表示匹配一个字符 0 次或者多次
字符区间 []:
[ ] 表示匹配某个范围内的一个字符
- [6,8]:匹配 6 或 8
- [0-9]:匹配一个 0-9 的数字
- [0-9]*:匹配任意长度的数字字符串
- [a-z]:匹配一个 a-z 之间的字符
- [a-z]*:匹配人资产固定额字母字符串
- [a-c, e-f]:匹配 a-c 或 e-f 之间的任意字符

特殊字符 \:
\ 表示转义,并不会单独使用。由于所有特殊字符有其特定的匹配模式,当我们相匹配其自身的时候需要结束 \ 进行转移(例如,想匹配文件名带有 “$”)。进行匹配时,需要用单引号 ‘ 括起来。
文本处理工具:
cut:
cut 的工作就是 “剪”,具体的说就是在文件中负责剪切数据。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
基本用法:cut [选项参数] filename
| 选项 | 功能描述 |
|---|---|
| -f | 列号,提取第几列 |
| -d | 分隔符,按照指定分隔符分割列,默认是制表符 “\t” |
| -c | 按字符进行切割,后加 n 表示取第几列 |

awk:
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分在进行分析处理。
- 基本用法:
awk [选项参数] '/pattern1/{action1} /pattern2/{action2}...' filename- pattern:表示 awk 在数据中查找的内容,就是匹配模式
- action:在找到匹配内容时所执行的一系列命令 | 选项 | 功能描述 | | —- | —- | | -F | 指定输入文件分割符 | | -v | 赋值一个用户定义变量 |
[root@CentOS-Study etc]# cat passwd | grep ^root | cut -d ":" -f 7/bin/bash[root@CentOS-Study etc]#[root@CentOS-Study etc]#[root@CentOS-Study etc]#[root@CentOS-Study etc]# cat passwd | awk -F ":" '/^root/ {print $7}'/bin/bash[root@CentOS-Study etc]#[root@CentOS-Study etc]#[root@CentOS-Study etc]# cat passwd | awk -F ":" '/^root/ {print $1","$7}'root,/bin/bash[root@CentOS-Study etc]#
