【shell脚本】字符串处理


引用文章:
Bash 基础知识系列 #6:处理字符串操作 | Linux 中国
菜鸟教程

前言:
  shell 脚本是一种非常实用的技能,而其中最为实用的不是各种 shell 命令,而是关于字符串处理的部分。

一、Bash 的字符串操作

  1. 获取字符串长度
    格式:${#string}
$ str1=aaaaa
$ echo {#str1}
结果> 5

$ str2="bbb"
$ echo {#str2}
结果> 3
  1. 连接字符串
    格式:str3=$str1$str2
$ str1="hello"
$ str2="world"
$ show=$str1$str2
$ echo "show: $show"
结果> show: helloworld
  1. 提取子字符串
    格式:${string:$pos:$len} pos从 0 开始
$ str=nihao
$ substr=${str:2:2}
$ echo $substr
结果> ha
  1. 替换 Bash 中的子字符串
    格式:
       替换第一次出现的子字符串:${string/substr1/substr2}
       替换所有出现的地方:   ${string//substr1/substr2}
$ statement="the bash is good shell"
$ statement=${statement/good/best}
$ echo $statement
结果> the bash is best shell
  1. 删除子字符串
    格式:
       仅删除第一次出现的子字符串:${string/substring}
       删除所有出现的内容:    ${string//substr}
$ string="itsfoss is awesome"
$ echo ${string/its}
结果> foss is awesome
  1. 截取子字符串
    格式:
       ${parameter#word}  # 删除匹配前缀 去掉左边,最短匹配模式
       ${parameter##word}  ##最长匹配模式
       ${parameter%word}   # 删除匹配后缀
       ${parameter%%word} # % 去掉右边,最短匹配模式,%%最长匹配模式
$ URL="http://www.baidu.com/baike/user.html"
$ echo ${URL#*//}
结果> www.baidu.com/baike/user.html
$ echo ${URL%%//*}
结果> http:

二、正则表达式

2.1 模式

  • 字面值字符:可以直接匹配它们自身。例如:字母、数字、空格等。
  • 特殊字符:具有特殊的含义和功能。例如:“.”、“*”、“+”、“?” 等。
  • 字符类:用于匹配方括号内的任意一个字符。用 [ ] 包围的字符集合
  • 元字符:用于匹配特定类型的字符。例如:\d、\w、\s等,对应 数字、字母、空白字符等
  • 量词:用于指定匹配的次数或范围。例如:{n}、{n, }、{n, m} 等。
  • 边界符号:用于匹配字符串的开头、结尾 或 单词边界位置。例如:“^”、“$”、“\b”、“\B” 等。

2.2 语法

正则表达式可以在文本中查找、替换、提取 和 验证 特定的模式。

2.2.1 普通字符

[ABC]、[^ABC](除 ABC 之外的字符)、[A-Z]、.(相当于[^\n\r])、
[\s\S](\s 是匹配所有空白符,包括换行,\S 是非空白符,不包括换行)、
\w(匹配 字母、数字、下划线)、\d(匹配任意一个阿拉伯数字)。

2.2.2 非打印字符

\cx(x是字母,\cM 匹配 Ctrl-M 或 回车)
剩下的都是转义字符,基于C语言理解即可。

2.2.3 特殊字符

特别字符描述
$匹配输入字符串的结尾位置。如果要匹配 $ 字符本身,使用 $。
()标记一个子表达式的 开始 和 结束 位置。
*匹配前面的子表达式 零次 或 多次。要匹配 * 字符,请使用 \*
+匹配前面的子表达式 一次 或 多次。要匹配 + 字符,请使用 \+
.匹配除换行符 \n 之外的任何单字符。要匹配 .,请使用 \.
[标记一个中括号表达式的开始。要匹配[,请使用 \[
?匹配前面的子表达式 零次 或 一次,或 指明 一个 非贪婪限定符。
要匹配 ? 字符,请使用 \?
\将下一个字符标记为 或 特殊字符、或原义字符、或向后引用、或八进制引用。
^匹配输入字符串的开始位置,除非在方括号表达式中使用。
{标记限定符表达式的开始。要匹配 { 字符,请使用 \{
|指明两项之间的一个选择。要匹配 |,轻松使用 |

2.2.4 限定符

字符描述
*匹配前面的子表达式 零次 或 多次。
+匹配前面的子表达式 一次 或 多次。
?匹配前面的子表达式零次或一次。
{n}n为非负整数。指定字符匹配 n 次。
{n, }n是一个非负整数,指定字符至少匹配 n 次。
{n, m}m 和 n 均为 非负整数,n <= m。最少匹配 n 次,且最多匹配 m 次。
  • 和 + 限定符 都是 贪婪的,因为它们会尽可能多的匹配文字,只有在它们后面加上一个 ? 就可以实现 非贪婪 或 最小匹配。
    非贪婪 —— 用 ?,只匹配一次。

2.2.5 定位符

字符描述
^匹配输入字符串 开始 的位置。
$匹配输入字符串 结尾 的位置。
\b匹配一个单词的 前 或 后 边界,即 字 与 空格间 的位置。
\B非单词边界匹配。

2.2.6 选择

用 () 将所有选择项括起来,相邻的选项之间用 | 分隔。
() 表示捕获分组,它会把每个分组里匹配的值保存起来(放在临时缓冲区),多个匹配值可以通过数字 n 来查看,表示第 n 个捕获组的内容。
副作用:相关的匹配会被缓存,此时可用 ?: 放在第一个选项前面 来消除这种副作用。
可以用 非捕获元字符 ?:、?=、?! 来重写捕获,忽略对相关匹配的保存。

关于临时缓冲区:
所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的 顺序 存储。
缓冲区编号从 1 开始,最多可存储 99 个捕获的 子表达式。
每个缓冲区可以使用 \n 来访问,n 为缓冲区的编号。

2.2.7 非捕获元(先行断言 和 后行断言)

?: 是 非捕获元 之一,还有两个非捕获元 是 ?=?!,它俩还有更多含义:
?= 是 正向预查,在任何开始 匹配 () 的正则表达式模式的位置来 匹配 搜索字符串
?! 是 反向预查,在任何开始 不匹配 () 的正则表达式模式的位置来 匹配 搜索字符串。

非捕获元格式功能
?=exp1(?=exp2)【正向先行断言】查找 exp2 前面的 exp1
?<=(?<=exp2)exp1【正向后行断言】查找 exp2 后面的 exp1
?!exp1(?!exp2)【负向先行断言】查找后面不是 exp2 的 exp1
?<!(?<!exp2)exp1【负向后行断言】查找前面是不是 exp2 的 exp1

2.2.8 反向引用

反向引用就是在 正则表达式 之后用 \n 访问 第 n 个临时缓冲区。如 2.2.6 所述,最大访问缓存区编号为 99。
反向引用 最简单、最有用 的应用之一是提供查找文本中两个相同的相邻单词的匹配项的能力。

2.3 修饰符(标记)

修饰符用于指定额外的匹配策略,位于表达式 之外,格式为 /pattern/flags

修饰符含义描述
iignore - 不区分大小写将匹配设置为不区分大小写
gglobal - 全局匹配查找所有的匹配项
mmulti line - 多行匹配使边界字符 ^ 和 $ 匹配每一行的 开头 和 结尾
s修饰 .,使其包含 \n默认情况下 “.” 是匹配除 \n 之外的任何字符

2.4 元字符

元字符就是之前讲的各种特殊符号和转移符号。

2.5 运算符优先级

顺序:从左到右,遵循优先级顺序
下表从高到低说明了各种运算符的优先级:

运算符描述
|转义符
(),(?😃,(?=),[]圆括号 和 方括号
*,+,?,{n},{n,},{n,m}限定符
^,$,\ 任何元字符、
任何字符
定位点 和 序列(即:位置和顺序)
|替换,“或”操作
字符具有高于替换运算符的优先级,使得

2.6 匹配规则

2.6.1 基本模式匹配

模式可以很简单,由普通的字符串组成,也可以非常复杂,用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。

2.6.2 字符簇

字符簇 就是 一种更自由的描述我们要的模式的方法。
如何支持多次匹配呢?
这时候就要用到 {} 来确定前面内容的重复次数了。
{x} —— 前面的 字符 或 字符簇 只出现 x 次
{x,} —— 前面的 内容 出现 x 或 更多次的次数
{x,y} —— 前面的 内容 至少出现 x 次,但不超过 y 次

三、相关命令

3.1 cut

  • 功能
    1、显示文件的内容,将其内容输出到 stdout 上
    2、合并两个或多个文件的内容【Eg:cut f1 f2 > f3
  • 字符串处理特征
    cut 可以支持按指定的字符划分字符串的功能。【按列处理】
-b:以字节为单位进行分割
-c:以字符为单位进行分隔【也可以指定一个范围,如:6-9】
-d:指定字段的 分隔符,默认的字段分隔符为 “tab”
-f:与 -d 合用,指定显示的区域(列号,提取第几列)

3.2 grep

  • 功能:用于查找指定文件里符合条件的 字符串,显示其所在的整行的字符。
-i:忽略大小写匹配
-n:显示匹配行的行号
-r:递归查找 子目录 中的文件
-c:纸打印匹配的行数
-A <显示行数>:除了显示符合条件的哪一行外,还显示其后的几行

3.3 sed

  • 功能:利用脚本来处理、编辑文本文件
-e <script>:以选项中指定的 script 来处理输入的文本文件
			 【表示多点编辑,即 同时操作多条 sed<script>-f <script文件>:以选项中指定的 script文件 来处理输入的文本文件
-n:仅显示 script 处理后的结果
== <script>格式 ================================================
a:新增。a后面的字符串会在下一行出现
c:取代。c后面的字符串可以取代 n1,n2 之间的行
d:删除。d后通常不接任何东西
i:插入。i后面的字符串会在上一行出现
p:打印。通常 p 会与 -n 一起运行
s:取代。可直接进行取代的工作,通常搭配 正则表达式
q:退出。

注意:
1、sed 后面的动作,务必以 ‘…’ 括住。
2、数据的搜寻并执行命令

$ nl testfile | sed -n '/oo/{s/oo/kk/;p;q}'
       5   Gkkgle

这里把 oo 替换为 kk,再输出,最后的 q 是退出。

3.4 awk

awk是一种处理文本文件的语言,是一个强大的文本分析工具

  • 语法:
    awk [选项参数] ‘script’ var=value file(s)

    awk [选项参数] -f scriptfile var=value file(s)
  • 参数:
-F:指定输入文件分隔符,一个字符,或 一个正则表达式。后面直接跟特定的符号即可。
	【多个分隔符,'[分隔符1分隔符2……]'】
-v:创建一个用户定义变量,并赋值
	【Eg:awk -va=1 '{printf $1,$1+a}' log.txt】
-f:从脚本文件中读取 awk 命令

============= log.txt =============
2 this is a test
3 Do you like awk
This's a test
10 There are orange,apple,mongo
===================================
swk '{[pattern] action}' {filenames} # 行匹配语句 awk ' ' 只能用单引号
# 1、每行按 空格 或 TAB 分隔,可指定项
$ awk '{print $1, $4}' log.txt
# 2、格式化输出
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
  • 运算符
运算符描述
=,+=,-=,/=,%=,^=,**=赋值
?:C条件表达式
||逻辑或
&&逻辑或
~,!~匹配 正则表达式 和 不匹配 正则表达式
<,<=,>,>=,!=,==关系运算符
空格连接
+,-加,减
*,/,%乘,除 与 求余
+,-,!一元 加,减 的 逻辑非
^***求幂
++,–增加 或 减少,作为 前缀 或 后缀
$字段引用
in数组成员
# 过滤 第一列 > 2 并且 第二列 = ‘Are’ 的行。
$ awk '$1>2 && $2=="Are" {print $1,$3}' log.txt
  • 内建变量(可以做出来按列输出的效果)
变量描述
$n当前记录的第 n 个字段,字段间由 FS 分隔
$0完整的输入记录
ARGC命令行参数的数目
ARGIND命令行中当前文件的位置(从0开始算)
ARGV包含命令行参数的数组
FILENAME当前文件名
FNR各文件分别计数的行号
IGNORECASE如果为真,忽略大小写匹配
NF一条记录的字段的数目
NR所读文件内容的行号,从1开始
  • 正则
    ~ 表示模式开始。/ / 中间的是 “模式”(可以直接是要匹配的内容,匹配的是行)
    ! 表示模式取反。
  • awk 脚本
    注意两个关键词 BEGIN 和 END
    BEGIN{ 这里面是 执行前 的语句 }
    END{ 这里面是 处理完所有的行后要执行的语句 }
    { 这里面是处理每一行时要执行的语句 }
    awk脚本的文件名:xxx.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0
 
    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

执行:awk -f xxx.awk yyy.txt

补充一个内容:grep、sed、awk 是Linux操作文本的三大利器,三者合称 文本三剑客。

四、查找

4.1 find

  • 按文件名查找:find 路径 -name ”文件名“
  • 按文件类型查找:·find 路径 -type 类型·
    类型:
    f —— 普通文件
    d —— 目录
    l —— 符号链接
    b —— 块设备文件
    c —— 字符设备文件
    s —— 套接字文件
    p —— 管道文件
  • 29
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值