iOS高级强化--015:Regular Expressions

正则表达式学习

正则表达式:是处理字符串的⼀种表达⽅式。提供了⼀种从⼀组字符串中
选择特定字符串的机制

POSIX规范定义了UNIX操作系统应当⽀持的功能,POSIX规范的正则表达式:

  • BRE:(Basic Regular Expression)基本型正则表达式
  • ERE:(Extended Regular Express)扩展型正则表达式

BREERE⼆者的区别,简单的说就在于(){}+?|7个特殊字符的使⽤⽅法上:

  • BRE中,如果想要这些字符表示特殊的含义,就需要把它们转义。元字符 (){}+?|必须转义之后才具有特殊含义,如\+\?\|,⽽且也⽀持\1\2之类反向引⽤
  • 反之,在ERE中,如果要这些字符不表示特殊的含义,就需要把它们转义。虽然BRE名为“基本”⽽ERE名为“扩展”,但ERE并不要求兼容BRE的语法,⽽是⾃成⼀体
  • BRE中的特殊字符:.\[^$*
  • ERE中的特殊字符多了7个,即:.\[^$*(){}+?|

正则表达式与通配符没有任何关系,不是包含关系

  • 通配符,是Shell提供的功能
  • 正则表达式只是⽤来处理字符串

如何学习正则表达式?

  • 背,一些特殊字符的意义
  • 实际练习

案例:

⼀个常⻅的正则表达式

^1[3-9](\d{9})$
  • ^:锚点操作符,匹配字符串的开头
  • [3-9]:列表操作符,只匹配中括号中的⼀个字符。-:范围操作符指定范围
  • \d:代表0-9数字
  • {9}:间隔运算符,匹配前⼀个元素⼏次
  • (\d{9}):分组/捕获组,定义⼀个⼦表达式
  • $:锚点操作符,匹配字符串的结尾
特殊符号的意义
直抒胸臆操作符:
类别 匹配类型 匹配字符
Cat 字符串Cat,属于串联 Cat,不能匹配Catt
C 字符C C
渣男操作符:
类别 匹配类型 匹配字符
. 匹配所有的字符,除了newlinenull 通吃lsp
重复操作符:
类别 匹配类型
* 匹配前⼀个元素0次或多次
+ 匹配前⼀个元素1次或多次
? 匹配前⼀个元素0次或1
间隔操作符 { ... }:
类别 匹配类型
{count} 匹配前⼀个元素count
{min,} 匹配前⼀个元素⾄少min
{min, max} 匹配前⼀个元素⾄少min次,⾄多max
备胎操作符:
类别 匹配类型 匹配字符
| 匹配前⼀个表达式或后⼀个表达式 在吗?我怀孕了
列表操作符 [ ... ] and [^ ... ] :

⼀般操作符在列表操作符⾥会失去特殊意义,除了:

类别 匹配类型
] 结束列表,[]]
\ 转义字符
[: 字符类别操作符开始
:] 字符类别操作符结束
- 范围操作符,0-9
字符类别操作符 [: ... :] :
类别 匹配类型 匹配字符
[:alnum:] [A-Za-z0-9] 数字和字⺟字符
[:alpha:] [A-Za-z] 字⺟字符
[:blank:] [ \t] 空格和TAB
[:cntrl:] [\x00-\x1F\x7F] 控制符
[:digit:] [0-9] 数字
[:graph:] [\x21-\x7E] 可视字符
[:lower:] [a-z] ⼩写字⺟字符
[:print:] [\x20-\x7E] 可视字符和空格(ASCII040-0176
[:punct:] ][!"#$%&'()*+,./:;<=>?@\^_`{|}~-] 标点符号
[:space:] [\t\r\n\v\f] 空⽩字符
[:upper:] [A-Z] ⼤写字⺟字符
[:xdigit:] [A-Fa-f0-9] ⼗六进制字符
特殊字符类别操作符:
类别 匹配类型 匹配字符
\w [:alnum:] 数字和字⺟字符
\d [:digit:] 数字
\W [^[:alnum:]] 除了数字和字⺟字符
\B [^[:digit:]] 除了数字
\< ^ 匹配字符串的开头
\> $ 匹配字符串的结尾
\b to\b匹配to!,但不匹配tomorrow 匹配单词边界字符
范围操作符:
类别 匹配类型
- 匹配指定范围,但是需在列表中使⽤,并指定范围,如[a-z][-az]或者[az-]表示匹配字⺟az还有-
锚点操作符:
类别 匹配类型
^ 匹配字符串的开头,需在开头
$ 匹配字符串的结尾或者换⾏符的前⼀个位置,需在结尾
  • 如果^在列表操作符中使⽤,并且在⾸位,代表取反
操作符优先级:
优先级(由⾼到低) 操作符
归类相关的括号符号 [::]
转义字符 \<特殊字符>
括号表达 []
分组 ()
单字符重复 * + ?{m, n}
串联 .
锚点 ^ $
备选 |
基础示例
grep
  • -v:逆转显示
  • -i:忽略⼤⼩写
  • -A:向上显示⼏⾏
  • -B:向下显示⼏⾏
  • -E:启⽤扩展
  • —color:显示颜⾊
egrep
  • 使用grep -E,启用ERE扩展型正则表达式

案例:

打开test.swift文件,写入以下文本:

struct LGTeacher {
   let name: String
   let class: String
   let credit:String
   let description: String
}

struct LGTeachers {
   let name: String
   let class: String
   let credit:String
   let description: String
}

extension LGTeacher {
   static var all: [LGTeacher] {
       [ LGTeacher(
           name: "Cooci",
           license: "http://creativecommons.org/licenses/by-sa/3.0",
           credit: "http://commons.wikimedia.org/wiki/User:Lin%C3%A91",
           description: "Basil is commonly used fresh in cooked recipes. In general, it is added at the last moment, as cooking quickly destroys the flavor. The fresh herb can be kept for a short time in plastic bags in the refrigerator, or for a longer period in the freezer, after being blanched quickly in boiling water. The dried herb also loses most of its flavor, and what little flavor remains tastes very different.9oo *oo"
       ),
       LGTeacher(
           name: "Kody",
           license: "http://creativecommons.org/licenses/by-sa/3.0",
           credit: "http://commons.wikimedia.org/wiki/User:Lin%C3%A91",
           description: "Saffron's aroma is often described by connoisseurs as reminiscent of metallic honey with grassy or hay-like notes, while its taste has also been noted as hay-like and sweet. Saffron also contributes a luminous yellow-orange colouring to foods. Saffron is widely used in Indian, Persian, European, Arab, and Turkish cuisines. Confectioneries and liquors also often include saffron."
       ),
       LGTeacher(
           name: "Hank",
           license: "http://creativecommons.org/licenses/by-sa/3.0",
           credit: "http://commons.wikimedia.org/wiki/User:Raul654",
           description: "Marjoram is used for seasoning soups, stews, dressings and sauce. Majorana has been scientifically proved to be beneficial in the treatment of gastric ulcer, hyperlipidemia and diabetes. Majorana hortensis herb has been used in the traditional Austrian medicine for treatment of disorders of the gastrointestinal tract and infections."
       ),
       LGTeacher(
           name: "CC",
           license: "http://www.gnu.org/licenses/old-licenses/fdl-1.2.html",
           credit: "http://commons.wikimedia.org/wiki/User:Fir0002",
           description: "The leaves, both fresh and dried, are used in traditional Italian cuisine. They have a bitter, astringent taste and are highly aromatic, which complements a wide variety of foods. Herbal tea can be made from the leaves. When burnt, they give off a mustard-like smell and a smell similar to burning wood, which can be used to flavor foods while barbecuing. Rosemary is high in iron, calcium and vitamin B6.")
       ,
       LGTeacher(
           name: "Cat",
           license: "http://commons.wikimedia.org/wiki/File:AniseSeeds.jpg",
           credit: "http://commons.wikimedia.org/wiki/User:Ben_pcc",
           description: "Anise is sweet and very aromatic, distinguished by its characteristic flavor. The seeds, whole or ground, are used in a wide variety of regional and ethnic confectioneries, including black jelly beans, British aniseed balls, Australian humbugs, and others. The Ancient Romans often served spiced cakes with aniseseed, called mustaceoe at the end of feasts as a digestive. "
       )
       ]
   }
}

匹配包含LG的内容

grep "LG" test.swift
-------------------------
struct LGTeacher {
struct LGTeachers {
extension LGTeacher {
   static var all: [LGTeacher] {
       [ LGTeacher(
       LGTeacher(
       LGTeacher(
       LGTeacher(
       LGTeacher(

匹配包含LG的内容,将每一行的匹配结果,都向下多显示一行

grep "LG" test.swift -A 1
-------------------------
struct LGTeacher {
   let name: String
--
struct LGTeachers {
   let name: String
--
extension LGTeacher {
   static var all: [LGTeacher] {
       [ LGTeacher(
           name: "Cooci",
--
       LGTeacher(
           name: "Kody",
--
       LGTeacher(
           name: "Hank",
--
       LGTeacher(
           name: "CC",
--
       LGTeacher(
           name: "Cat",

匹配包含LG的内容,将每一行的匹配结果,上下各多显示一行

grep "LG" test.swift -A 1 -B 1
-------------------------

struct LGTeacher {
   let name: String
--
--

struct LGTeachers {
   let name: String
--
--

extension LGTeacher {
   static var all: [LGTeacher] {
       [ LGTeacher(
           name: "Cooci",
--
--
       ),
       LGTeacher(
           name: "Kody",
--
--
       ),
       LGTeacher(
           name: "Hank",
--
--
       ),
       LGTeacher(
           name: "CC",
--
--
       ,
       LGTeacher(
           name: "Cat",

匹配包含lgteacher的内容,忽略大小写

grep "lgteacher" test.swift -i
-------------------------
struct LGTeacher {
struct LGTeachers {
extension LGTeacher {
   static var all: [LGTeacher] {
       [ LGTeacher(
       LGTeacher(
       LGTeacher(
       LGTeacher(
       LGTeacher(

匹配过滤LGTeacher后的内容

grep "LGTeacher" test.swift -v

匹配包含LGTeacher的内容,但不匹配LGTeachers

grep "LGTeacher[^s]" test.swift
-------------------------
struct LGTeacher {
extension LGTeacher {
   static var all: [LGTeacher] {
       [ LGTeacher(
       LGTeacher(
       LGTeacher(
       LGTeacher(
       LGTeacher(

匹配包含oo的内容

grep "oo" test.swift

匹配包含oo的内容,过滤前面由小写字母开头的内容

grep "[^a-z]oo" test.swift
//或者
grep "[^[:lower:]]oo" test.swift

匹配包含oo的内容,只保留数字或符号开头的内容

grep "[^A-Za-z]oo" test.swift

匹配包含oo的内容,只保留数字开头的内容

grep "[0-9]oo" test.swift
//或者
grep "\doo" test.swift

匹配包含oo的内容,只保留符号开头的内容

grep "[^A-Za-z0-9]oo" test.swift
//或者
grep "\Woo" test.swift

匹配包含oo的内容,过滤前面由符号开头的内容

grep "[A-Za-z0-9]oo" test.swift
//或者
grep "\woo" test.swift

使用.占中间两位,匹配C开头,ci结尾的内容

grep "C..ci" test.swift
-------------------------
name: "Cooci",

匹配C开头,使用.占后两位的内容

grep "C.." test.swift
  • .:匹配所有的字符,除了newlinenull

匹配Co开头,使用*占后一位的内容

grep "Co*" test.swift
  • *:匹配前⼀个元素0次或多次

匹配Coo开头,使用*占后一位的内容

grep "Coo*" test.swift

匹配C开头,后面接两个o的内容

grep -E "Co{2}" test.swift
-------------------------
name: "Cooci",
  • 间隔操作符{ ... },是ERE中支持的特殊符号。grep命令支持ERE表达式,需要增加-E参数
分组与向后引⽤

分组\捕获组操作符(( ... ) or \( ... \))

  • 定义⼀个⼦表达式。正则表达式将此序列视为⼀个单元。圆括号在整体匹配完后进⾏匹配
  • 可以配合反向引⽤操作符,重复使⽤分组匹配的结果

反向引⽤操作符(\digit)

  • 反向引⽤操作符由\数字表示,数字需介于1-9,代表引⽤那个分组的匹配结果

案例1:

匹配包含oo的内容,只保留数字开头的内容,使用(\d)进行分组

grep -E "(\d)oo" test.swift
  • 分组( ... ),是ERE中支持的特殊符号。grep命令支持ERE表达式,需要增加-E参数

案例2:

通过\1获取第一个分组内容

grep -E "description(.*)(\1)" test.swift
  • 反向引⽤操作符(\digit),代表引⽤那个分组的匹配结果
\ 字符

以下内容在部分语⾔中不⽀持

每种环境,⽆论是PythonPerlJavaC#Ruby还是其他,在实现正则表达式时都有特殊的差别。Swift也不例外

Objective-CSwift都要求您转义⽂字字符串中的特殊字符(即,在它们
前⾯加反斜杠\字符)。反斜杠本身就是这样的特殊字符之⼀。由于⽤于创建
正则表达式的模式也是字符串,因此会增加复杂性,因为在使⽤Stringand
需要转义反斜杠字符NSRegularExpression

这意味着标准正则表达式\.将出现\\.在您的Swift(或Objective-C)代码中

  • ⽂字\\.定义了⼀个类似于以下字符串:\.
  • 正则表达式\.然后将匹配单个句点字符
贪婪模式

贪婪模式、勉强模式与侵占模式:

贪婪匹配 勉强匹配 侵占匹配 作⽤
X? X?? X?+ 匹配X零次或⼀次
X* X*? X*+ 匹配X零次或多次
X+ X+? X++ 匹配X⼀次或多次
X{n} X{n}? X{n}+ 匹配Xn
X{n,} X{n,}? X{n,}+ 匹配X⾄少n
X{n,m} X{n,m}? X{n,m}+ 匹配X⾄少n次,但不多于m

案例1:

匹配test.swift文件中,description相关内容

grep "description.*\"$" test.swift
//或者
grep -E "description(.*)[\"]$" test.swift

案例2:

假定要分析的字符串是xfooxxxxxxfoo

模式.*foo(贪婪模式)由两部分

  • p1(.*)
  • p2(foo)

查看匹配结果,其中p1中的匹配⽅式使⽤默认⽅式(贪婪型)

  • 第⼀轮:匹配开始时,p1匹配所有字符xfooxxxxxx,匹配成功,但p2⽆匹配字符,本轮匹配失败
  • 第⼆轮:减少p1部分的匹配量,留出最后⼀个字符, 此时存在两个字符串,s1代表xfooxxxxxxfos2代表os1匹配p1, 但s2不匹配p2。本轮匹配失败
  • 第三轮,继续减少p1匹配量,留出两个字符, 字符串被分割成xfooxxxxxxfooo两部分。结果同上
  • 第四轮,再次减少p1匹配量,字符串分割成xfooxxxxxxfoo两个部分,这次p1/p2同时匹配。返回匹配成功

案例3:

模式.*?foo(勉强模式)最⼩匹配⽅式

  • p1(.*?)
  • p2(foo)

查看匹配结果,其中p1中的匹配⽅式使⽤勉强模式匹配

  • 第⼀轮:p1由于是0或任意次,⾸先匹配0次。所以直接⽤字符串去匹配p2,但p2⽆匹配字符,本轮匹配失败
  • 第⼆轮:增加p1部分的匹配量,匹配x。此时存在两个字符串,s1代表xs2代表fooxxxxxxfoos1匹配p1, 但s2不匹配p2。本轮匹配失败;继续上述匹配直到满⾜p2

案例4:

模式.*+foo(侵占模式)

  • p1(.*+)
  • p2(foo)

查看匹配结果,其中p1中的匹配⽅式使⽤侵占模式匹配

  • 匹配开始时读⼊所有字符串,和p1匹配成功,但没有剩余字符串去和p2匹配。匹配失败

简单地说,贪婪模式和侵占模式相⽐,贪婪模式会在只有部分匹配成功的条件下,依次从多到少减少匹配成功部分模式的匹配数量,将字符留给模式其他部分去匹配。⽽侵占模式则是占有所有能匹配成功部分,绝不留给其他部分使⽤

案例5:

使用(fooq|foo)*(qbarquux|bar)完全匹配的字符串是?

  • A、fooqbarquux
  • B、fooqbar
  • C、以上都选

仅选项B可以完全匹配,选项A只能匹配出fooqbar前半部分

案例6:

使用((a*)b)*\1\2完全匹配的字符串是?

  • A、aabababa
  • B、aabaabaabaabaa
  • C、以上都选

答案为选项C,选项AB都可以完全匹配

  • 如果分组不⽌⼀次匹配(例如,如果后⾯跟着重复运算符),则
    向后引⽤将匹配分组最后匹配的⼦字符串

案例7:

使用(one(x)|two(y))-and-(three\2|four\3)完全匹配的字符串是?

  • A、onex-and-threex
  • B、twoy-and-foury
  • C、onex-and-four
  • D、twoy-and-threey
  • E、twoy-and-threex

选项AB都可以完全匹配

  • 分组\2\3分别对应(x)(y),当(x)匹配失败,分组\2的位置存在,但分组报错
  • 当访问报错的分组,匹配将会中断

案例8:

t.swift文件中,删除description节点

使用description:(\W)(.*)将匹配的内容替换为空

结尾的渣男操作符.,除newlinenull匹配所有字符

案例9:

licensecredit的值,都改为https://www.baidu.com/

使用(license|credit):[\W](.)*将匹配的内容替换为$1: "https://www.baidu.com/",

  • $1表示分组\1(license|credit)
更⾼级的⽤法
零宽断⾔

断⾔:在指定位置应该满⾜⼀定的条件

当捕获组以开头时?=,表示该组将被⽤作零宽度正预测先⾏断⾔,仅当前⼀个模式与捕获组中的模式相匹配时才与前⼀个模式匹配。例如,A(?=B)A匹配,并且⻢上跟着B。可以匹配ABABBACB

Unicode

匹配特定类别的Unicode字符\p{ ... }

  • \p{L}所有字符,\p{Lu}所有⼩写字符,\p{N}
  • \P{}匹配不特定类别的Unicode字符
sed命令

sed命令:可以将数据进⾏替换、删除、新增、选取特定内容等功能,⽤作⼀整⾏字符处理

命令格式

sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)

选项

-e
                    
                    

你可能感兴趣的:(iOS高级强化--015:Regular Expressions)