# Shell概述
Shell是一个命令解释器,它在操作系统的最底层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户。这种对话方式可以是交互的方式(从键盘输入命令,可以立即得到shell的回应),或非交互(脚本)的方式。
命令行解释器:使用户得以与内核进行沟通的“翻译官”
# Shell解析器
- Linux提供的Shell解析器有:
[root@hadoop101 ~]$ cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
2
3
4
5
6
7
- bash和sh的关系
bash 是 Bourne Again Shell 是Linux标准的默认shell ,它基于Bourne shell,吸收了C shell和Korn shell的一些特性。bash完全兼容Bourne shell,也就是说用Bourne shell的脚本不加修改可以在bash中执行。
sh 是Bourne shell 这个是UNIX标准的默认shell,对它评价是concise简洁 compact紧凑 fast高效 有AT&T编写,属于系统管理shell。
[root@hadoop101 bin]$ ll | grep bash
-rwxr-xr-x. 1 root root 941880 5月 11 2016 bash
lrwxrwxrwx. 1 root root 4 5月 27 2017 sh -> bash
2
3
- Centos默认的解析器是bash
[root@hadoop102 bin]$ echo $SHELL
/bin/bash
2
3
# Shell 脚本入门
# Shell使用
- 脚本格式
脚本以#!/bin/bash开头(指定解析器) - 第一个Shell脚本:helloworld
1)需求:创建一个Shell脚本,输出 helloworld
2)案例实操:
[root@hadoop101 datas]$ touch helloworld.sh
[root@hadoop101 datas]$ vi helloworld.sh
2
在helloworld.sh中输入如下内容
#!/bin/bash
echo "helloworld"
2
3)脚本的常用执行方式
第一种:采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本 +x 权限)
sh+脚本的相对路径
[root@hadoop101 datas]$ sh helloworld.sh
Helloworld
2
sh+脚本的绝对路径
[root@hadoop101 datas]$ sh /home/root/datas/helloworld.sh
helloworld
2
bash+脚本的相对路径
[root@hadoop101 datas]$ bash helloworld.sh
Helloworld
2
bash+脚本的绝对路径
[root@hadoop101 datas]$ bash /home/root/datas/helloworld.sh
Helloworld
2
第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x) (a)首先要赋予helloworld.sh 脚本的+x权限
[root@hadoop101 datas]$ chmod 777 helloworld.sh
(b)执行脚本 相对路径
[root@hadoop101 datas]$ ./helloworld.sh
Helloworld
2
绝对路径
[root@hadoop101 datas]$ /home/root/datas/helloworld.sh
Helloworld
2
3
注意:第一种执行方法,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限。第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。
3. 第二个Shell脚本:多命令处理
1)需求
在/home/root/目录下创建一个banzhang.txt,在banzhang.txt文件中增加“I love cls”。
2)案例实操
[root@hadoop101 datas]$ touch batch.sh
[root@hadoop101 datas]$ vi batch.sh
2
在batch.sh中输入如下内容
#!/bin/bash
cd /home/root
touch cls.txt
echo "I love cls" >>cls.txt
2
3
4
# echo命令
Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。命令格式:
echo string
您可以使用echo实现更复杂的输出格式控制。
- 显示普通字符串
echo "It is a test"
这里的双引号完全可以省略,以下命令与上面实例效果一致:
echo It is a test
- 显示转义字符
echo "\"It is a test\""
结果将是:
"It is a test"
同样,双引号也可以省略
3. 显示变量
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
#!/bin/sh
read name
echo "$name It is a test"
2
3
以上代码保存为 test.sh,name 接收标准输入的变量,结果将是:
[root@www ~]# sh test.sh
OK #标准输入
OK It is a test #输出
2
3
- 显示换行
echo -e "OK! \n" # -e 开启转义
echo "It is a test"
2
输出结果:
OK!
It is a test
2
- 显示不换行
#!/bin/sh
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
2
3
输出结果:
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。
printf 命令的语法:
printf format-string [arguments...]
参数说明:
- format-string: 为格式控制字符串
- arguments: 为参数列表。
实例
$ echo "Hello, Shell"
Hello, Shell
$ printf "Hello, Shell\n"
Hello, Shell
2
3
4
接下来,我来用一个脚本来体现 printf 的强大功能:
实例
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
2
3
4
执行脚本,输出结果如下所示:
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
2
3
4
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。
%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中 .2 指保留2位小数。
实例
# format-string为双引号
printf "%d %s\n" 1 "abc"
# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"
# 没有引号也可以输出
printf %s abcdef
# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def
printf "%s\n" abc def
printf "%s %s %s\n" a b c d e f g h i j
# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
执行脚本,输出结果如下所示:
1 abc
1 abc
abcdefabcdefabc
def
a b c
d e f
g h i
j
and 0
2
3
4
5
6
7
8
9
printf 的转义序列
序列 | 说明 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\c | 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 |
\f | 换页(formfeed) |
\n | 换行 |
\r | 回车(Carriage return) |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 一个字面上的反斜杠字符 |
\ddd | 表示1到3位数八进制值的字符。仅在格式字符串中有效 |
\0ddd | 表示1到3位的八进制值字符 |
实例
$ printf "a string, no processing:<%s>\n" "A\nB"
a string, no processing:<A\nB>
$ printf "a string, no processing:<%b>\n" "A\nB"
a string, no processing:<A
B>
$ printf "www.runoob.com \a"
www.runoob.com $ #不换行
2
3
4
5
6
7
8
9
# Shell中的变量
# 系统变量
- 常用系统变量
$HOME、$PWD、$SHELL、$USER等 - 案例实操
1)查看系统变量的值
[root@hadoop101 datas]$ echo $HOME
/home/root
2
2)显示当前Shell中所有变量:set
[root@hadoop101 datas]$ set
BASH=/bin/bash
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
2
3
4
5
# 自定义变量
- 基本语法
1)定义变量:变量=值
2)撤销变量:unset 变量
3)声明静态变量:readonly变量,注意:不能unset
4)除了显式地直接赋值,还可以用语句给变量赋值,如:
for file in `ls /etc`
或
for file in $(ls /etc)
2
3
- 变量类型
运行shell时,会同时存在三种变量:
1). 局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
2).环境变量
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。
3). shell变量
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的运行。 - 变量定义规则
1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
2)等号两侧不能有空格
3)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
4)变量的值如果有空格,需要使用双引号或单引号括起来。 - 案例实操
1)定义变量A
[root@hadoop101 datas]$ A=5
[root@hadoop101 datas]$ echo $A 或者 ${A}
5
2
3
2)给变量A重新赋值
[root@hadoop101 datas]$ A=8
[root@hadoop101 datas]$ echo $A
8
2
3
3)撤销变量A
[root@hadoop101 datas]$ unset A
[root@hadoop101 datas]$ echo $A
2
4)声明静态的变量B=2,不能unset
[root@hadoop101 datas]$ readonly B=2
[root@hadoop101 datas]$ echo $B
2
[root@hadoop101 datas]$ B=9
-bash: B: readonly variable
2
3
4
5
5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
[root@hadoop102 ~]$ C=1+2
[root@hadoop102 ~]$ echo $C
1+2
2
3
6)变量的值如果有空格,需要使用双引号或单引号括起来
[root@hadoop102 ~]$ D=I love banzhang
-bash: world: command not found
[root@hadoop102 ~]$ D="I love banzhang"
[root@hadoop102 ~]$ echo $A
I love banzhang
2
3
4
5
7)可把变量提升为全局环境变量,可供其他Shell程序使用 export 变量名
[root@hadoop101 datas]$ vim helloworld.sh
在helloworld.sh文件中增加echo $B
#!/bin/bash
echo "helloworld"
echo $B
2
3
[root@hadoop101 datas]$ ./helloworld.sh
Helloworld
2
发现并没有打印输出变量B的值。
[root@hadoop101 datas]$ export B
[root@hadoop101 datas]$ ./helloworld.sh
helloworld
2
2
3
4
# 特殊变量表
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项,与set命令 (opens new window)功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
# 特殊变量:$n
- 基本语法
$n (功能描述:n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}) - 案例实操
1)输出该脚本文件名称、输入参数1和输入参数2 的值
[root@hadoop101 datas]$ touch parameter.sh
[root@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
[root@hadoop101 datas]$ chmod 777 parameter.sh
[root@hadoop101 datas]$ ./parameter.sh cls xz
./parameter.sh cls xz
2
3
4
5
6
7
# 特殊变量:$#
- 基本语法
$# (功能描述:获取所有输入参数个数,常用于循环) - 案例实操
1)获取输入参数的个数
[root@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
[root@hadoop101 datas]$ chmod 777 parameter.sh
[root@hadoop101 datas]$ ./parameter.sh cls xz
parameter.sh cls xz
2
2
3
4
5
6
7
8
# 特殊变量:$*、$@
- 基本语法
$* (功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体)
$@ (功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待) - 案例实操
1)打印输入的所有参数
[root@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
echo $*
echo $@
[root@hadoop101 datas]$ bash parameter.sh 1 2 3
parameter.sh 1 2
3
1 2 3
1 2 3
2
3
4
5
6
7
8
9
10
11
# 特殊变量:$?
- 基本语法
$? (功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。) - 案例实操
1)判断helloworld.sh脚本是否正确执行
[root@hadoop101 datas]$ ./helloworld.sh
hello world
[root@hadoop101 datas]$ echo $?
0
2
3
4
# Shell 字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
- 单引号
str='this is a string'
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
- 双引号
your_name='runoob'
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str
2
3
输出结果为:
Hello, I know you are "runoob"!
双引号的优点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
- 拼接字符串
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
2
3
4
5
6
7
8
9
输出结果为:
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !
2
4.获取字符串长度
string="abcd"
echo ${#string} #输出 4
2
5.提取子字符串
以下实例从字符串第 2 个字符开始截取 4 个字符:
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
2
提示
第一个字符的索引值为 0。
- 查找子字符串
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
2
提示
以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。
# Shell 数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
- 定义数组
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)
例如:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
2
3
4
5
6
还可以单独定义数组的各个分量:
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
2
3
可以不使用连续的下标,而且下标的范围没有限制。
2. 读取数组
读取数组元素值的一般格式是:
${数组名[下标]}
例如:
valuen=${array_name[n]}
使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}
- 获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同,例如:
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
2
3
4
5
6
# shell 注释
shell有单行注释和多行注释
# 单行注释
单行注释使用#号开头。
# 多行注释
多行注释可以使用以下格式:
:<<EOF
注释内容...
注释内容...
注释内容...
EOF
2
3
4
5
EOF 也可以使用其他符号:
:<<'
注释内容...
注释内容...
注释内容...
'
:<<!
注释内容...
注释内容...
注释内容...
!
2
3
4
5
6
7
8
9
10
11
# shell 运算符
- 基本语法
1)“$((运算式))”或“$[运算式]”
2)expr + , - , *, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格 - 案例实操:
1)计算3+2的值
[root@hadoop101 datas]$ expr 2 + 3
5
2
2)计算3-2的值
[root@hadoop101 datas]$ expr 3 - 2
1
2
3)计算(2+3)X4的值
a)expr一步完成计算
[root@hadoop101 datas]$ expr `expr 2 + 3` \* 4
20
2
b)采用$[运算式]方式
[root@hadoop101 datas]# S=$[(2+3)*4]
[root@hadoop101 datas]# echo $S
2
# shell 条件判断
- 基本语法
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ root ]返回true,[] 返回false。 - 常用判断条件
1)两个整数之间比较
| 参数 | 说明 | | :--- | :------------- | | -eq | 等于则为真 | | -ne | 不等于则为真 | | -gt | 大于则为真 | | -ge | 大于等于则为真 | | -lt | 小于则为真 | | -le | 小于等于则为真 | 2)按照文件权限进行判断
-r 有读的权限(read) -w 有写的权限(write)
-x 有执行的权限(execute)
2
3)按照文件类型进行判断
参数 | 说明 |
---|---|
-e 文件名 | 如果文件存在则为真 |
-r 文件名 | 如果文件存在且可读则为真 |
-w 文件名 | 如果文件存在且可写则为真 |
-x 文件名 | 如果文件存在且可执行则为真 |
-s 文件名 | 如果文件存在且至少有一个字符则为真 |
-d 文件名 | 如果文件存在且为目录则为真 |
-f 文件名 | 如果文件存在且为普通文件则为真 |
-c 文件名 | 如果文件存在且为字符型特殊文件则为真 |
-b 文件名 | 如果文件存在且为块特殊文件则为真 |
4)字符串条件判断
参数 | 说明 |
---|---|
= | 等于则为真 |
!= | 不相等则为真 |
-z 字符串 | 字符串的长度为零则为真 |
-n 字符串 | 字符串的长度不为零则为真 |
5)Shell test 命令
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
3. 案例实操
1)23是否大于等于22
[root@hadoop101 datas]$ [ 23 -ge 22 ]
[root@hadoop101 datas]$ echo $?
0
2
3
2)helloworld.sh是否具有写权限
[root@hadoop101 datas]$ [ -w helloworld.sh ]
[root@hadoop101 datas]$ echo $?
0
2
3
3)/home/demo/cls.txt目录中的文件是否存在
[root@hadoop101 datas]$ [ -e /home/root/cls.txt ]
[root@hadoop101 datas]$ echo $?
1
2
3
4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[root@hadoop101 ~]$ [ condition ] && echo OK || echo notok
OK
[root@hadoop101 datas]$ [ condition ] && [ ] || echo notok
notok
2
3
4
5)字符串测试(结合 test 命令)
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
2
3
4
5
6
7
8
# shell 流程控制
# if 判断
- 基本语法
if 语句语法格式:
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
fi
2
3
4
5
6
7
8
9
10
if else 语法格式:
if [ 条件判断式 ]
then
程序
else
程序
fi
2
3
4
5
6
7
if else-if else 语法格式:
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
2
3
4
5
6
7
8
9
10
11
注意事项:
1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
2)if后要有空格
- 案例实操
1)输入一个数字,如果是1,则输出banzhang zhen shuai,如果是2,则输出cls zhen mei,如果是其它,什么也不输出。
[root@hadoop101 datas]$ touch if.sh
[root@hadoop101 datas]$ vim if.sh
#!/bin/bash
if [ $1 -eq "1" ]
then
echo "banzhang zhen shuai"
elif [ $1 -eq "2" ]
then
echo "cls zhen mei"
fi
[root@hadoop101 datas]$ chmod 777 if.sh
[root@hadoop101 datas]$ ./if.sh 1
banzhang zhen shuai
2
3
4
5
6
7
8
9
10
11
12
13
14
# case 语句
- 基本语法
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
2
3
4
5
6
7
8
9
10
11
12
注意事项:
- case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
- 双分号“****;;****”表示命令序列结束,相当于java中的break。
- 最后的“*)”表示默认模式,相当于java中的default。
- 案例实操
1)输入一个数字,如果是1,则输出banzhang,如果是2,则输出cls,如果是其它,输出renyao。
[root@hadoop101 datas]$ touch case.sh
[root@hadoop101 datas]$ vim case.sh
!/bin/bash
case $1 in
"1")
echo "banzhang"
;;
"2")
echo "cls"
;;
*)
echo "renyao"
;;
esac
[root@hadoop101 datas]$ chmod 777 case.sh
[root@hadoop101 datas]$ ./case.sh 1
banzhang
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# for 循环
- 基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
2
3
4
5
- 案例实操
1)从1加到100
[root@hadoop101 datas]$ touch for1.sh
[root@hadoop101 datas]$ vim for1.sh
#!/bin/bash
s=0
for((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
[root@hadoop101 datas]$ chmod 777 for1.sh
[root@hadoop101 datas]$ ./for1.sh
"5050"
2
3
4
5
6
7
8
9
10
11
12
13
- 基本语法2
for 变量 in 值1 值2 值3…
do
程序
done
2
3
4
- 案例实操
1)打印所有输入参数
[root@hadoop101 datas]$ touch for2.sh
[root@hadoop101 datas]$ vim for2.sh
#!/bin/bash
#打印数字
for i in $*
do
echo "ban zhang love $i "
done
[root@hadoop101 datas]$ chmod 777 for2.sh
[root@hadoop101 datas]$ bash for2.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
2
3
4
5
6
7
8
9
10
11
12
13
14
2)比较$*和$@区别
a)$*和$@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 $2 …$n的形式输出所有参数。
[root@hadoop101 datas]$ touch for.sh
[root@hadoop101 datas]$ vim for.sh
#!/bin/bash
for i in $*
do
echo "ban zhang love $i "
done
for j in $@
do
echo "ban zhang love $j"
done
[root@hadoop101 datas]$ bash for.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
b)当它们被双引号“ ”包含时,“$*”会将所有的参数作为一个整体,以“$1 $2 …$n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “$2”…”$n”的形式输出所有参数。
[root@hadoop101 datas]$ vim for.sh
#!/bin/bash
for i in "$*"
#$*中的所有参数看成是一个整体,所以这个for循环只会循环一次
do
echo "ban zhang love $i"
done
for j in "$@"
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
echo "ban zhang love $j"
done
[root@hadoop101 datas]$ chmod 777 for.sh
[root@hadoop101 datas]$ bash for.sh cls xz bd
ban zhang love cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# while 循环
- 基本语法
while [ 条件判断式 ]
do
程序
done
2
3
4
无限循环语法格式:
while :
do
程序
done
2
3
4
或者
while true
do
程序
done
2
3
4
或者
for (( ; ; ))
- 案例实操
1)从1加到100
[root@hadoop101 datas]$ touch while.sh
[root@hadoop101 datas]$ vim while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
[root@hadoop101 datas]$ chmod 777 while.sh
[root@hadoop101 datas]$ ./while.sh
5050
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# until 循环
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
until 语法格式:
until [ 条件判断式 ]
do
程序
done
2
3
4
condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
以下实例我们使用 until 命令来输出 0 ~ 9 的数字:
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
2
3
4
5
6
7
运行结果:
0
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
10
# read 读取控制台输入
1.基本语法
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
2
3
4
5
6
- 案例实操
1)提示7秒内,读取控制台输入的名称
[root@hadoop101 datas]$ touch read.sh
[root@hadoop101 datas]$ vim read.sh
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds " NAME
echo $NAME
[root@hadoop101 datas]$ ./read.sh
Enter your name in 7 seconds xiaoze
xiaoze
2
3
4
5
6
7
8
9
10
# shell 函数
# 系统函数
# basename
- 功能
返回完整路径最后/的后面部分,常用于获取文件名。 - 基本语法
basename [string / pathname] [suffix]
选项:
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。 - 案例实操
1)截取该/home/root/banzhang.txt路径的文件名称
[root@hadoop101 datas]$ basename /home/root/banzhang.txt
banzhang.txt
[root@hadoop101 datas]$ basename /home/root/banzhang.txt .txt
banzhang
2
3
4
# dirname
- 功能
从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分) - 基本语法
dirname 文件绝对路径 - 案例实操
获取banzhang.txt文件的路径
[root@hadoop101 ~]$ dirname /home/root/banzhang.txt
/home/root
2
# 自定义函数
- 基本语法
[ function ] funname[()]
{
Action;
[return int;]
}
funname
2
3
4
5
6
- 经验技巧
1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
3.案例实操
1)计算两个输入参数的和
[root@hadoop101 datas]$ touch fun.sh
[root@hadoop101 datas]$ vim fun.sh
#!/bin/bash
function sum()
{
s=0
s=$[ $1 + $2 ]
echo "$s"
}
read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2;
[root@hadoop101 datas]$ chmod 777 fun.sh
[root@hadoop101 datas]$ ./fun.sh
Please input the number1: 2
Please input the number2: 5
7
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...
带参数的函数示例:
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
2
3
4
5
6
7
8
9
10
输出结果:
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
2
3
4
5
6
7
# Shell 输入/输出重定向
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
重定向命令列表如下:
命令 | 说明 |
---|---|
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)。
# shell 重重定向
# shell 输入重定向
和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:
command1 < file1
这样,本来需要从键盘获取输入的命令会转移到文件读取内容。
注意:输出重定向是大于号(>),输入重定向是小于号(<
实例:
接着以上实例,我们需要统计 users 文件的行数,执行以下命令:
$ wc -l users
2 users
2
也可以将输入重定向到 users 文件:
$ wc -l < users
2
2
注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。
command1 < infile > outfile
同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。
# shell 输出重定向
重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:
command1 > file1
上面这个命令执行command1然后将输出的内容存入file1。
注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。
实例:
执行下面的 who 命令,它将命令的完整的输出重定向在用户文件中(users):
$ who > users
执行后,并没有在终端输出信息,这是因为输出已被从默认的标准输出设备(终端)重定向到指定的文件。
你可以使用 cat 命令查看文件内容:
$ cat users
_mbsetupuser console Oct 31 17:35
tianqixin console Oct 31 17:35
tianqixin ttys000 Dec 1 11:33
2
3
4
输出重定向会覆盖文件内容,请看下面的例子:
$ echo "数媒实验室" > users
$ cat users
数媒实验室
$
2
3
4
如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾,例如:
$ echo "数媒实验室" >> users
$ cat users
数媒实验室
数媒实验室
$
2
3
4
5
# shell 重定向深入理解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
$ command 2>file
如果希望 stderr 追加到 file 文件末尾,可以这样写:
$ command 2>>file
提示
2 表示标准错误文件(stderr)。
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
$ command > file 2>&1
或者
$ command >> file 2>&1
2
3
如果希望对 stdin 和 stdout 都重定向,可以这样写:
$ command < file1 >file2
command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
# Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
command << delimiter
document
delimiter
2
3
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
- 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
- 开始的delimiter前后的空格会被忽略掉。
实例:
在命令行中通过 wc -l 命令计算 Here Document 的行数:
$ wc -l << EOF
欢迎
来到
数媒实验室
EOF
3 # 输出结果为 3 行
$
2
3
4
5
6
7
我们也可以将 Here Document 用在脚本中,例如:
#!/bin/bash
cat << EOF
欢迎来到
数媒实验室
EOF
2
3
4
5
6
执行以上脚本,输出结果:
欢迎来到
数媒实验室
2
# /dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
**注意:**0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。 这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。
# Shell工具
# cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
- 基本用法
cut [选项参数] filename
说明:默认分隔符是制表符
2. 选项参数说明
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列 |
- 案例实操
1)数据准备
[root@hadoop101 datas]$ touch cut.txt
[root@hadoop101 datas]$ vim cut.txt
dong shen
guan zhen
wo wo
lai lai
le le
2
3
4
5
6
7
2)切割cut.txt第一列
[root@hadoop101 datas]$ cut -d " " -f 1 cut.txt
dong
guan
wo
lai
le
2
3
4
5
6
3)切割cut.txt第二、三列
[root@hadoop101 datas]$ cut -d " " -f 2,3 cut.txt
shen
zhen
wo
lai
le
2
3
4
5
6
4)在cut.txt文件中切割出guan
[root@hadoop101 datas]$ cat cut.txt | grep "guan" | cut -d " " -f 1
guan
2
5)选取系统PATH变量值,第2个“:”开始后的所有路径:
[root@hadoop101 datas]$ echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/root/bin
[root@hadoop102 datas]$ echo $PATH | cut -d: -f 2-
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/root/bin
2
3
4
5
6)切割ifconfig 后打印的IP地址
[root@hadoop101 datas]$ ifconfig eth0 | grep "inet addr" | cut -d: -f 2 | cut -d" " -f1
192.168.1.102
2
# sed
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的
内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
- 基本用法
sed [参数] 'command' filename
- 参数说明 | 选项参数 | 功能 | | -------- | ------------------------------------- | | -e | 直接在指令列模式上进行sed的动作编辑。 |
- 命令功能描述 | 命令 | 功能描述 | | ---- | ------------------------------------- | | a | 新增,a的后面可以接字串,在下一行出现 | | d | 删除 | | s | 查找并替换 |
- 案例实操 1)数据准备
[root@hadoop102 datas]$ touch sed.txt
[root@hadoop102 datas]$ vim sed.txt
dong shen
guan zhen
wo wo
lai lai
le le
2
3
4
5
6
7
8
2)将“mei nv”这个单词插入到sed.txt第二行下,打印。
[root@hadoop102 datas]$ sed '2a mei nv' sed.txt
dong shen
guan zhen
mei nv
wo wo
lai lai
le le
[root@hadoop102 datas]$ cat sed.txt
dong shen
guan zhen
wo wo
lai lai
le le
2
3
4
5
6
7
8
9
10
11
12
13
14
15
注意:文件并没有改变
3)删除sed.txt文件所有包含wo的行
[root@hadoop102 datas]$ sed '/wo/d' sed.txt
dong shen
guan zhen
lai lai
le le
2
3
4
5
6
4)将sed.txt文件中wo替换为ni
[root@hadoop102 datas]$ sed 's/wo/ni/g' sed.txt
dong shen
guan zhen
ni ni
lai lai
le le
2
3
4
5
6
7
注意:‘g’表示global,全部替换
5)将sed.txt文件中的第二行删除并将wo替换为ni
[root@hadoop102 datas]$ sed -e '2d' -e 's/wo/ni/g' sed.txt
dong shen
ni ni
lai lai
le le
2
3
4
5
6
# awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
- 基本用法
awk [参数] ‘pattern1{action1} pattern2{action2}...’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令 - 参数说明 | 选项参数 | 功能 | | -------- | -------------------- | | -F | 指定输入文件折分隔符 | | -v | 赋值一个用户定义变量 |
- 案例实操 1)数据准备
[root@hadoop102 datas]$ sudo cp /etc/passwd ./
2)搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
[root@hadoop102 datas]$ awk -F: '/^root/{print $7}' passwd
/bin/bash
2
3)搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。
[root@hadoop102 datas]$ awk -F: '/^root/{print $1","$7}' passwd
root,/bin/bash
2
注意:只有匹配了pattern的行才会执行action
4)只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"dahaige,/bin/zuishuai"。
[root@hadoop102 datas]$ awk -F : 'BEGIN{print "user, shell"} {print $1","$7} END{print "dahaige,/bin/zuishuai"}' passwd
user, shell
root,/bin/bash
bin,/sbin/nologin
。。。
root,/bin/bash
dahaige,/bin/zuishuai
2
3
4
5
6
7
注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。
5)将passwd文件中的用户id增加数值1并输出
[root@hadoop102 datas]$ awk -v i=1 -F: '{print $3+i}' passwd
1
2
3
4
2
3
4
5
awk的内置变量 | 变量 | 说明 | | -------- | -------------------------------------- | | FILENAME | 文件名 | | NR | 已读的记录数 | | NF | 浏览记录的域的个数(切割后,列的个数) |
案例实操
1)统计passwd文件名,每行的行号,每行的列数
[root@hadoop102 datas]$ awk -F: '{print "filename:" FILENAME ", linenumber:" NR ",columns:" NF}' passwd
filename:passwd, linenumber:1,columns:7
filename:passwd, linenumber:2,columns:7
filename:passwd, linenumber:3,columns:7
2
3
4
2)切割IP
[root@hadoop102 datas]$ ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}' | awk -F " " '{print $1}'
192.168.1.102
2
3)查询sed.txt中空行所在的行号
[root@hadoop102 datas]$ awk '/^$/{print NR}' sed.txt
5
2
# sort
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。
- 基本语法
sort(选项)(参数)
| 选项 | 说明 | | ---- | ------------------------ | | -n | 依照数值的大小排序 | | -r | 以相反的顺序来排序 | | -t | 设置排序时所用的分隔字符 | | -k | 指定需要排序的列 | 参数:指定待排序的文件列表 - 案例实操
1)数据准备
[root@hadoop102 datas]$ touch sort.sh
[root@hadoop102 datas]$ vim sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
2
3
4
5
6
7
2)按照“:”分割后的第三列倒序排序。
[root@hadoop102 datas]$ sort -t : -nrk 3 sort.sh
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6
2
3
4
5
6
# 正则表达式
# 正则表达式简介
正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。
正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。
支持正则表达式的程序如:locate |find| vim| grep| sed |awk
# 正则元字符一栏表
元字符:在正则中,具有特殊意义的专用字符,如: 星号(*)、加号(+)等
前导字符:元字符前面的字符叫前导字符
元字符 | 功能 | 示例 |
---|---|---|
* | 前导字符出现0次或者连续多次 | ab* abbbb |
. | 除了换行符以外,任意单个字符 | ab. ab8 abu |
.* | 任意长度的字符 | ab.* adfdfdf |
[] | 括号里的任意单个字符或一组单个字符 | [abc][0-9][a-z] |
[^] | 不匹配括号里的任意单个字符或一组单个字符 | [^abc] |
[3] | 匹配以括号里的任意单个字符开头 | [4] |
^[^] | 不匹配以括号里的任意单个字符开头 | |
^ | 行的开头 | ^root |
$ | 行的结尾 | bash$ |
^$ | 空行 | |
{n}和{n} | 前导字符连续出现n次 | [0-9]{3} |
{n,}和{n,} | 前导字符至少出现n次 | [a-z]{4,} |
{n,m}和{n,m} | 前导字符连续出现n-m次 | go{2,4} |
<> | 精确匹配单词 | <hello> |
() | 保留匹配到的字符 | (hello) |
+ | 前导字符出现1次或者多次 | [0-9]+ |
? | 前导字符出现0次或者1次 | go? |
| | 或 | ^root|^ftp |
() | 组字符 | (hello|world)123 |
\d | perl内置正则 | grep -P \d+ |
\w | 匹配字母数字下划线 |
# 正则表达式名词
- 元字符
指那些在正则表达式中具有特殊意义的专用字符,如:点(.) 星(*) 问号(?)等 - 前导字符 位于元字符前面的字符. abc* aooo.
# 常用元字符
元字符 | 功能 | 备注 |
---|---|---|
. | 匹配除了换行符以外的任意单个字符 | |
* | 前导字符出现0次或连续多次 | |
.* | 任意长度字符 | ab.* |
^ | 行首(以...开头) | ^root |
$ | 行尾(以...结尾) | bash$ |
^$ | 空行 | |
[] | 匹配括号里任意单个字符或一组单个字符 | [abc] |
[^] | 匹配不包含括号里任一单个字符或一组单个字符 | [^abc] |
[1] | 匹配以括号里任意单个字符或一组单个字符开头 | [2] |
^[^] | 匹配不以括号里任意单个字符或一组单个字符开头 | ^[^abc] |
- 示例文本
# cat 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
10.1.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
hello world
helloworld yourself
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 举例说明
# 其他元字符
元字符 | 功能 | 备注 |
---|---|---|
< | 取单词的头 | |
> | 取单词的尾 | |
< > | 精确匹配 | |
{n} | 匹配前导字符连续出现n次 | |
{n,} | 匹配前导字符至少出现n次 | |
{n,m} | 匹配前导字符出现n次与m次之间 | |
( ) | 保存被匹配的字符 | |
\d | 匹配数字(grep -P) | [0-9] |
\w | 匹配字母数字下划线(grep -P) | [a-zA-Z0-9_] |
\s | 匹配空格、制表符、换页符(grep -P) | [\t\r\n] |
举例说明
需求:将10.1.1.1替换成10.1.1.254
1)vim编辑器支持正则表达式
# vim 1.txt
:%s#\(10.1.1\).1#\1.254#g
:%s/\(10.1.1\).1/\1.254/g
2)sed支持正则表达式【后面学】
# sed -n 's#\(10.1.1\).1#\1.254#p' 1.txt
10.1.1.254
说明:
找出含有10.1.1的行,同时保留10.1.1并标记为标签1,之后可以使用\1来引用它。
最多可以定义9个标签,从左边开始编号,最左边的是第一个。
需求:将helloworld yourself 换成hellolilei myself
# vim 1.txt
:%s#\(hello\)world your\(self\)#\1lilei my\2#g
# sed -n 's/\(hello\)world your\(self\)/\1lilei my\2/p' 1.txt
hellolilei myself
# sed -n 's/helloworld yourself/hellolilei myself/p' 1.txt
hellolilei myself
# sed -n 's/\(hello\)world your\(self\)/\1lilei my\2/p' 1.txt
hellolilei myself
Perl内置正则:
\d 匹配数字 [0-9]
\w 匹配字母数字下划线[a-zA-Z0-9_]
\s 匹配空格、制表符、换页符[\t\r\n]
# grep -P '\d' 1.txt
# grep -P '\w' 2.txt
# grep -P '\s' 3.txt
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 扩展类常用元字符
- grep你要用我,必须加 -E 或者 让你兄弟
egrep
来找我 - sed你要用我,必须加 -r
扩展元字符 | 功能 | 备注 |
---|---|---|
+ | 匹配一个或多个前导字符 | bo+ 匹配boo、 bo |
? | 匹配零个或一个前导字符 | bo? 匹配b、 bo |
| | 或 | 匹配a或b |
() | 组字符(看成整体) | (my|your)self:表示匹配myself或匹配yourself |
{n} | 前导字符重复n次 | |
{n,} | 前导字符重复至少n次 | |
{n,m} | 前导字符重复n到m次 |
举例说明:
# grep "root|ftp|adm" /etc/passwd
# egrep "root|ftp|adm" /etc/passwd
# grep -E "root|ftp|adm" /etc/passwd
# grep -E 'o+gle' test.txt
# grep -E 'o?gle' test.txt
# egrep 'go{2,}' 1.txt
# egrep '(my|your)self' 1.txt
使用正则过滤出文件中的IP地址:
# grep '[0-9]\{2\}\.[0-9]\{1\}\.[0-9]\{1\}\.[0-9]\{1\}' 1.txt
10.1.1.1
# grep '[0-9]{2}\.[0-9]{1}\.[0-9]{1}\.[0-9]{1}' 1.txt
# grep -E '[0-9]{2}\.[0-9]{1}\.[0-9]{1}\.[0-9]{1}' 1.txt
10.1.1.1
# grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' 1.txt
10.1.1.1
# grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt
10.1.1.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
第二类正则
表达式 | 功能 | 示例 |
---|---|---|
[:alnum:] | 字母与数字字符 | [[:alnum:]]+ |
[:alpha:] | 字母字符(包括大小写字母) | [[:alpha:]]{4} |
[:blank:] | 空格与制表符 | [[:blank:]]* |
[:digit:] | 数字 | [[:digit:]]? |
[:lower:] | 小写字母 | [[:lower:]]{4,} |
[:upper:] | 大写字母 | [[:upper:]]+ |
[:punct:] | 标点符号 | [[:punct:]] |
[:space:] | 包括换行符,回车等在内的所有空白 | [[:space:]]+ |
[root@server shell05]# grep -E '^[[:digit:]]+' 1.txt
[root@server shell05]# grep -E '^[^[:digit:]]+' 1.txt
[root@server shell05]# grep -E '[[:lower:]]{4,}' 1.txt
2
3
正则表达式总结
- 我要找什么?
- 找数字 [0-9]
- 找字母 [a-zA-Z]
- 找标点符号 [[:punct:]]
- 我要如何找?看心情找
- 以什么为首 ^key
- 以什么结尾 key$
- 包含什么或不包含什么 [abc] ^[abc] [^abc] ^[^abc]
- 我要找多少呀?
- 找前导字符出现0次或连续多次 ab==*==
- 找任意单个(一次)字符 ab==.==
- 找任意字符 ab==.*==
- 找前导字符连续出现几次 {n} {n,m} {n,}
- 找前导字符出现1次或多次 go==+==
- 找前到字符出现0次或1次 go==?==
← SpringBoot 标准定义 →