文章目录
- 一、函数
-
- [1. 系统函数:basename](#1. 系统函数:basename)
- [2. 系统函数:dirname](#2. 系统函数:dirname)
- [3. 自定义函数](#3. 自定义函数)
- 二、正则表达式入门
-
- [1. 常规匹配](#1. 常规匹配)
- [2. 特殊字符 `^`:匹配一行的开头](#2. 特殊字符
^:匹配一行的开头) - [3. 特殊字符 `\`:匹配一行的结束](#3. 特殊字符 ``:匹配一行的结束)
- [4. 特殊字符 `.`:匹配一个任意字符](#4. 特殊字符
.:匹配一个任意字符) - [5. 特殊字符 `*`:匹配前一个字符 0 次或多次](#5. 特殊字符
*:匹配前一个字符 0 次或多次) - [6. 字符区间(中括号)` `:匹配某个范围内的一个字符](#6. 字符区间(中括号)
[ ]:匹配某个范围内的一个字符) - [7. 特殊字符 `\`:转义](#7. 特殊字符
\:转义)
- 三、文本处理工具:cut
- 四、文本处理工具:awk
- 五、总结
一、函数
1. 系统函数:basename
基本语法:
shell
basename [string / pathname] [suffix]
功能描述: basename 命令会删掉所有的前缀包括最后一个 / 字符,然后将字符串显示出来。可以理解为取路径里的文件名称 。其中 suffix 为后缀,如果指定了 suffix,basename 会将 pathname 或 string 中的 suffix 去掉。
案例实操: 截取 /home/xiaoxiaoguai/test.txt 路径的文件名称。
shell
basename /home/xiaoxiaoguai/test.txt
# test.txt
basename /home/xiaoxiaoguai/test.txt .txt
# test
2. 系统函数:dirname
基本语法:
shell
dirname 文件绝对路径
功能描述: 从给定的包含绝对路径的文件名中,去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)。可以理解为取文件所在目录的路径。
案例实操: 获取 test.txt 文件的路径。
shell
dirname /home/xiaoxiaoguai/test.txt
# /home/xiaoxiaoguai
3. 自定义函数
基本语法:
shell
[ function ] funname[()]
{
Action;
[return int;]
}
经验技巧:
- 必须在调用函数地方之前先声明函数------Shell 脚本是逐行运行的,不会像其他语言一样先编译。
- 函数返回值只能通过
$?系统变量获得。可以显式加return返回;如果不加,将以最后一条命令的运行结果作为返回值。return后跟数值 n(0-255)。
案例实操: 计算两个输入参数的和。
shell
touch func.sh
vim func.sh
shell
#!/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
执行:
shell
chmod 777 func.sh
[root@node1 ~]# ./func.sh
Please input the number1: 3
Please input the number2: 3
6
补充 :在函数内部可以使用
local声明局部变量,变量作用域仅限于该函数,避免污染全局环境:
shellfunction test() { local x=10 echo $x }
二、正则表达式入门
正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
在 Linux 中,grep、sed、awk 等文本处理工具都支持通过正则表达式进行模式匹配。
1. 常规匹配
一串不包含特殊字符的正则表达式匹配它自己:
shell
cat /etc/passwd | grep xiaoxiaoguai
# 匹配出所有包含 xiaoxiaoguai的行
2. 特殊字符 ^:匹配一行的开头
shell
cat /etc/passwd | grep ^a
# 匹配出所有以 a 开头的行
3. 特殊字符 $:匹配一行的结束
shell
cat /etc/passwd | grep t$
# 匹配出所有以 t 结尾的行
4. 特殊字符 .:匹配一个任意字符
shell
cat /etc/passwd | grep r..t
# 匹配出包含 r 开头、t 结尾(中间任意两个字符)的所有行
5. 特殊字符 *:匹配前一个字符 0 次或多次
shell
# * 不单独使用,它和上一个字符连用,表示匹配上一个字符 0 次或多次
cat /etc/passwd | grep ro*t
# 匹配 rt、rot、root、rooot、roooot 等所有行
6. 字符区间(中括号)[ ]:匹配某个范围内的一个字符
shell
[68] # 匹配 6 或者 8
[0-9] # 匹配一个 0-9 的数字
[0-9]* # 匹配任意长度的数字字符串
[a-z] # 匹配一个 a-z 之间的字符
[a-z]* # 匹配任意长度的字母字符串
[a-ce-f] # 匹配 a-c 或者 e-f 之间的任意字符
案例实操:
shell
cat /etc/passwd | grep r[abc]*t
# 匹配 rt、rat、rbt、rabt、rbact、rabccbaaacbt 等等所有行
注意:
[6,8]这种写法会把逗号也当作可匹配字符,表示 6、,、8 三者之一;想要匹配 6 或 8 应写作[68]。同理,区间合并应写成[a-ce-f]。
7. 特殊字符 \:转义
\ 表示转义,不会单独使用。由于所有特殊字符都有其特定匹配模式,当想匹配某一特殊字符本身时(例如找出所有包含 $ 的行),就要将转义字符和特殊字符连用,来表示特殊字符本身:
shell
cat /etc/passwd | grep 'a\$b'
# 匹配所有包含 a$b 的行,注意需要使用单引号将表达式引起来
三、文本处理工具:cut
cut 的工作就是"剪"------在文件中负责剪切数据,从每一行剪切字节、字符和字段并输出。
基本语法:
shell
cut [选项参数] filename
# 说明:默认分隔符是制表符(Tab)
常用选项:-d 指定分隔符,-f 指定要取的列。
案例实操:
shell
# 数据准备
touch cut.txt
vim cut.txt
# 添加以下内容
zhang san
li si
wang wu
shu jia
lan zhi
shell
# 1、切割 cut.txt 第一列(-d 指定分隔符为空格,-f 指定列号)
cut -d " " -f 1 cut.txt
# zhang
# li
# wang
# shu
# lan
# 2、切割 cut.txt 第二、三列
cut -d " " -f 2,3 cut.txt
# 3、在 cut.txt 中先过滤出含 shu 的行,再切割出第一列
cat cut.txt | grep shu | cut -d " " -f 1
# shu
# 4、选取系统 PATH 变量值中,第 2 个 ":" 开始后的所有路径
echo $PATH | cut -d ":" -f 3-
# 5、切割 ifconfig 输出中的 IP 地址
ifconfig ens33 | grep netmask | cut -d " " -f 10
提示:
ifconfig输出的缩进格式会因系统/版本而异,用cut取固定列号不够通用,更稳妥的做法是使用 awk 按字段精确提取(见下文):
shellifconfig ens33 | awk '/netmask/ {print $2}'另外,网卡名称(如 ens33)在不同机器上可能不同,请以实际环境为准。
四、文本处理工具:awk
awk 是一个强大的文本分析工具 :把文件逐行读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
基本语法:
shell
awk [选项参数] '/pattern1/{action1} /pattern2/{action2}...' filename
pattern:表示 awk 在数据中查找的内容,即匹配模式;action:在找到匹配内容时所执行的一系列命令。
案例实操:
shell
# 数据准备
cp /etc/passwd ./
/etc/passwd 每行各字段含义:用户名:密码(加密后):用户id:组id:注释:用户家目录:shell解析器
shell
# 1、搜索 passwd 文件中以 root 开头的所有行,并输出该行的第 7 列
# -F : 表示以冒号为分隔符
awk -F : '/^root/{print $7}' passwd
# /bin/bash
# 2、搜索以 root 开头的行,输出第 1 列和第 7 列,中间以 "," 分割
awk -F : '/^root/{print $1","$7}' passwd
# root,/bin/bash
# 注意:只有匹配了 pattern 的行才会执行 action
# 3、显示 passwd 的第一列和第七列,以逗号分割,
# 所有行前面添加列名 user,shell,最后一行添加 "lanzhishujia,/bin/bigdata"
awk -F : 'BEGIN{print "user, shell"} {print $1","$7} END{print "lanzhishujia,/bin/bigdata"}' passwd
# 注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行
# 4、将 passwd 文件中的用户 id 增加数值 1 并输出(-v 用于传外部变量给 awk)
awk -v i=1 -F : '{print $3+i}' passwd
awk 的内置变量:
| 内置变量 | 含义 |
|---|---|
FILENAME |
当前输入文件的文件名 |
NR |
已读出的记录数(行号) |
NF |
当前记录(行)的字段个数 |
$NF |
当前行的最后一列(补充) |
案例实操:
shell
# 1、统计 passwd 文件名、每行的行号、每行的列数
awk -F : '{print "filename:" FILENAME ",linenum:" NR ",col:"NF}' passwd
# 2、查询 ifconfig 命令输出结果中空行所在的行号
ifconfig | awk '/^$/{print NR}'
# 3、切割 IP(awk 方式,比 cut 取固定列更稳定)
ifconfig ens33 | awk '/netmask/ {print $2}'
五、总结
| 知识点 | 关键内容 |
|---|---|
| 系统函数 | basename 取文件名、dirname 取目录路径 |
| 自定义函数 | [ function ] funname() { ... [return n;] },先声明后调用 |
| 正则元字符 | ^ $ . * [ ] \ |
| cut | -d 指定分隔符、-f 指定列,默认分隔符为制表符 |
| awk | -F 分隔符、pattern/action、BEGIN/END、-v 传变量 |
| awk 内置变量 | FILENAME、NR、NF、$NF |