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/bash
echo '===================$n==============='
echo $0
echo $1
echo $2
[root@CentOS-Study script]#
[root@CentOS-Study script]# chmod 777 parameter.sh
[root@CentOS-Study script]# ./parameter.sh cls xz
===================$n===============
./parameter.sh
cls
xz
[root@CentOS-Study script]#
$#:
$# 获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强交办的健壮性。
[root@CentOS-Study script]# vim parameter.sh
#!/bin/bash
echo '===================$n==============='
echo $0
echo $1
echo $2
echo '===================$#==============='
echo $#
[root@CentOS-Study script]#
[root@CentOS-Study script]# ./parameter.sh cls xz
===================$n===============
./parameter.sh
cls
xz
===================$#===============
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.sh
a
b
===================$#===============
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.sh
bash: 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/bash
echo '================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
-1
44
[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/bash
if [ 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/bash
case $变量名 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/bash
for 变量 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/bash
echo '===========$*================'
for par in "$*"
do
echo $par
done
echo '===========$@================'
for par in "$@"
do
echo $par
done
[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
===========$@================
a
b
c
d
[root@CentOS-Study script]#
while 循环:
基本用法:
[root@CentOS-Study script]# touch parameter_while_test.sh
[root@CentOS-Study script]# vim parameter_while_test.sh
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]
do
sum=$[$sum+$i]
i=$[$i+1]
done
echo $sum
[root@CentOS-Study script]#
[root@CentOS-Study script]# chmod +x parameter_while_test.sh
[root@CentOS-Study script]# ./parameter_while_test.sh
5050
[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]# ls
computing.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.sh
read_test.sh
[root@CentOS-Study script]#
[root@CentOS-Study script]# basename /root/script/read_test.sh .sh
read_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/bash
function sum(){
s=0
s=$[$1+$2]
echo $s
}
read -p "the first number: " a
read -p "the second number: " b
result=$(sum $a $b)
echo $result
[root@CentOS-Study script]# chmod +x fun_test.sh
[root@CentOS-Study script]# ./fun_test.sh
the first number: 5
the second number: 3
8
[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]#