【golang】正则表达式 查找和替换字符

Go 专栏收录该内容
16 篇文章 0 订阅

算法第四版部分章节总结,熟悉正则表达式,需知正则描述模式和正则常用缩略写法。
一、正则描述模式
二、正则缩略写法 (闭包简写,字符集,元字符)
三、正则实践 (字符串查找,字符串替换,网页标签匹配)

正则表示式,就是在一个字符串之中查找满足要求的子字符串

一、正则表达式的描述模式,

连接操作

连接操作就是匹配连接后的结果
有 hello和 go 两个单词将它们连接起来,用正则表式为 (hello)(go),就是连接操作,如果正则有了,但是字符串只有hello是匹配不会成功的,必须满足匹配规则的全部要求

连接操作匹配一个邮箱 (示例:abcabc@qq.com)

操作12345
拆分成邮箱名 abcabc小老鼠 @服务商域名 qq点 .国际域名 com
对应正则[\w]{5,15}@[\w]+.[a-zA-Z]{2,14}

完整的正则 : [\w]{5,15}@[\w]+\.[a-zA-Z]+

连接操作取出网页中的价格 (< div>< span class=“price”> 55.9< /span>< /div>)

操作123
拆分<span class=“price”>55.9</span>
对应正则\ <span class=“price”>[\d\.]\ </span>

完整正则 \<span class="price">[\d\.]+\</span>
以上结果会取到这一整个标签,需要把这个匹配结果二次操作,取出其中的价格 [\d\.]+

或操作

或操作就是指定多个匹配结果,
与程序中的 | or 相似,满足其中一个条件就可以了。例如手机号码的匹配,常用号码由13 15 17 18 19 开头,用正则写匹配开头2位 (13|15|17|18|19),或操作用括号包起来,因为这是整个表示式中的其中一个整体,后面的9位[0-9]{9},
连起来就是 (13|15|17|18|19)[0-9]{9}

闭包操作

闭包就是把一个匹配规则重复任意次数,
注册一个用户名,长度可能5位,也可以8位、15位,闭包就可以多次匹配,如[a-z] 默认只匹配一次,匹配结果是a-z中的一个字母,使用闭包操作就是 [a-z]+,那么它将会匹配1次到无数次,因为闭包操作中 + 的匹配字数是至少 1 次。
闭包有以下几种操作, 详细说明见下闭包的简写
? + * {}

但凡涉及到这几个操作符号的 那么就有包含闭包,有 | 号的就是包括或操作,有连接的就是包括连接操作,正则之中这三种操作是重点。

括号

使用括号来改变默认的优先级顺序,与程序中的()是一样一样的,
例如
X(A|B)Z ,匹配的结果 [XAZ, XBZ] ,
*X|A|B|Z,无括号匹配的结果 [X, A, B, Z] *
X|(A|B|Z) ,匹配结果 [XA,XB,XZ],
(X|Y)(A|B)C,匹配结果 [XAC, XBC, YAC, YBC]


二、缩略写法

就像我们力求写出最简洁的程序和高效的算法 一样,避免表达式冗余

字符集

通配符,匹配任意一个字符,中括号内的字符表示匹配其中的任意个,范围集合,指定的范围内的字符,补集即括号内以外的任意字符

名称记法示例
通配符. 匹配除换行符以外的任意字符abc.,
范围集合用[]包括,指定某一范围内的值 用 - 来表示[0-9][0-5][a-z]
指定集合用[]包括,指定在为某几个值[aeiou]*
补集用[]包含,首字符为 ^[^aeiou]*

闭包的简写

闭包的意思是把一个操作复制任意次数,?号一次或者0次,+号一次或者多次,*号0次或者多次,{}指定次数

闭包以下几种操作,

符号匹配的字符长度
?一个或者 0 次
+一次或者多次
*0次或者多次
{n}指定重复次数等于 n
{n,m}次数 n 到 m , 示例: {1,5} 1-5次。{2,}至少2次 , {,5}最多5次

转义序列

* ? . + /是正则中的元字符,在它们前面加转义符号\,它们就是没有语义的普通字符
*在正则中是匹配0或无数次,\*则表示一个普通的字符*,
\表示转义 \\则表示一个普通字符\,
还有一些特殊字符, \t制表符,\n换行符, \s空白字符, \d数字

常用元字符

代码说明
.匹配除换行符以外的任意字符除“\n”之外的任何单个字符
\w匹配字母或数字或下划线等价于“[A-Za-z0-9_]”。
\s匹配任意的空白符等价于 [ \f\n\r\t\v]
\d匹配数字等价于[0-9]
\b匹配单词的开始或结束单词 never, ne\b可以匹配到ne,
er\b 可以匹配到er,但不能匹配 verb 中的er
^匹配字符串的开始
$匹配字符串的结束

其它元字符
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

大写元字符匹配结果与小写元字符相反,示例: \W, \S, \D, \B ,等于 [^\w] ,[\s],[\d],[^\b]

正则表达式, 在编写处理字符串的程序或网页时,经常有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

正则在线测试: http://tool.chinaz.com/regex/

三、正则实践

go语言正则表达式查找字符串示例

package main 

import(
	"regexp"
	"fmt"
)

func main() {

	text :="Abc a7c MFC 8ca. 你好! Golang/"
	
	//查找连续的小写字母	
	reg := regexp.MustCompile(`[a-z]{2,}`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1))// [bc ca olang]
}

查找连续的非小写字母

	reg = regexp.MustCompile(`[^a-z]{2,}`)
	fmt.Printf("%s\n",reg.FindAllString(text, -1))//[ MFC 8 . 你好! G]

查找连续的单词字母

	reg = regexp.MustCompile(`[a-zA-Z]{2,}`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1))//[Abc MFC ca Golang]

查找连续的非单词字母、非空白字符

	reg = regexp.MustCompile(`[^a-zA-Z\s]+`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1)) //[7 8 . 你好! /]

查找连续的大写字母

	reg = regexp.MustCompile(`[A-Z]+`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1)) //[A MFC G]

查找 abc 或 Golang

	reg = regexp.MustCompile(`(abc|Golang)`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1)) //[Golang]

查找以 G开头,以 / 结尾的单词

	reg = regexp.MustCompile(`G[\w.]*\/`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1)) //[Golang/]

查找从行首开始,以空格结尾的字符串

	reg = regexp.MustCompile(`[\w]+\s`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1)) //[Abc  a7c  MFC ]

查找连续 1 次到 4 次的非空格字符,并以 c 结尾的字符串

	reg = regexp.MustCompile(`[^\s]{1,4}c`)
	fmt.Printf("%s\n", reg.FindAllString(text, -1)) //[Abc a7c 8c]

go语言正则表达式字符串替换示例

package main 

import(
	"regexp"
	"fmt"
)

func main() {

	text :="Abc a7c MFC 8ca. 你好! Golang/"
	
	// 查找 Abc 或 a7c,替换为 Abccc a7ccc
	reg = regexp.MustCompile(`(Ab|a7)c`)
	fmt.Printf("%q\n", reg.ReplaceAllString(text, `${1}ccc`)) //"Abccc a7ccc MFC 8ca. 你好! Golang/"
}

查找 Abc 或 a7c 或 你好 ,替换为**号

	reg = regexp.MustCompile(`(Abc|a7c|你好)`)
	fmt.Printf("%s\n", reg.ReplaceAllString(text, "**"))  //** ** MFC 8ca. **! Golang/

在每个单词后面加上 , 号

	reg = regexp.MustCompile(`([\w.]+)\s`)
	fmt.Printf("%s\n", reg.ReplaceAllString(text, "${1},")) //Abc,a7c,MFC,8ca.,你好! Golang/

把 a 开头的单词 更改成大写 A

	reg = regexp.MustCompile(`[a](\w.)`)
	fmt.Printf("%s\n", reg.ReplaceAllString(text, `A${1}`)) //Abc A7c Aa MFC 8ca. 你好! GolAng/

交换 Abc 和 Golang

	reg = regexp.MustCompile(`(Abc)(.*)(Golang)`)
	fmt.Printf("%s\n", reg.ReplaceAllString(text, `${3}${2}${1}`))  //Golang a7c MFC 8ca. 你好! Abc/

go语言 正则表达式 获取网页标签内的数据 示例

package main 

import(
	"regexp"
	"fmt"
	"io/ioutil"
)

func main() {
	//读取文件
	f,err := ioutil.ReadFile("./spider-page/regexp-1A0001.html")
	if err != nil {
		fmt.Print(err)
	}
	str := string(f)

		//获取 <h1>标题内的文字 
	reg := regexp.MustCompile(`<strong>(?s:(.*?))</strong>(.*)`)
	text := reg.FindAllStringSubmatch(str, -1)
	fmt.Printf("%s-%s\n",text[0][1],text[0][2]) // 上证指数-1A0001
}

获取今天最低价格

	reg = regexp.MustCompile(`<strong id="tlowprice">(?s:(.*?))</strong>`)
	text = reg.FindAllStringSubmatch(str, -1)
	fmt.Printf("最低价:%s\n",text[0][1]) // 最低价:2533.36

获取今天最高价格

	reg = regexp.MustCompile(`<strong id="thighprice">(?s:(.*?))</strong>`)
	text = reg.FindAllStringSubmatch(str, -1)
	fmt.Printf("最高价:%s\n",text[0][1]) // 最高价:2554.79

获取当前时间

	reg = regexp.MustCompile(`<span class="price" id="hexm_curPrice">(?s:(.*?))</span>`)
	text = reg.FindAllStringSubmatch(str, -1)
	fmt.Printf("当前价:%s\n",text[0][1]) // 当前价:2553.83

获取当前价格

	reg = regexp.MustCompile(`<p id="timeshow">(?s:(.*?))</p>`)
	text = reg.FindAllStringSubmatch(str, -1)
	fmt.Printf("当前时间:%s\n",text[0][1]) // 当前时间:2019年1月12日 15:00:00

返回结果
上证指数-1A0001
最低价:2533.36
最高价:2554.79
当前价:2553.83
当前时间:2019年1月12日 15:00:00

regexp-1A0001.html(示例文件)

<h1 class="m_logo fl">
    <strong>上证指数</strong>1A0001
</h1>
<div class="new_detail fl">
    <div class="price_box fl price_box_wide" id="hexm_curPrice_wrap">
          <div class="clearfix plus_price" id="quote_header">
              <span class="price" id="hexm_curPrice">2553.83</span>
              <div class="price_details">
                  <span class="plus_rate" id="hexm_float_price">18.73</span>
                  <span class="price_plus" id="hexm_float_rate">0.74%</span>
              </div> 
          </div>
          <div class="minute_price ting clearfix" id="quote_header2">
              <span class="price"><a href="###">停牌</a></span>                 
          </div>
       <div class="minute_price_ztdt fl">
              <p>涨停:<span class="red" id="tmaxprice">0</span>跌停:<span class="green" id="tminprice">0</span></p>
              <p id="timeshow">2019年1月12日 15:00:00</p>
          </div>
    </div>
    <ul class="new_trading fl">
        <li>
            <span class="jk">今开:<strong class="minus" id="topenprice">2539.55</strong></span>
            <span class="contract_amount">成交量:<strong id="tamount" class="plus">149.4亿</strong></span>
            <span class="zf">振幅:<strong id="trange">0.85%</strong></span>
        </li>
        <li>
            <span class="zg">最高:<strong id="thighprice">2554.79</strong></span>
            <span class="trading_volume">成交额:<strong id="tamounttotal">1223.8亿</strong></span>
            <span class="hs">换手:<strong id="tchange">0.45%</strong></span>
        </li>
        <li>
            <span class="zd">最低:<strong id="tlowprice">2533.36</strong></span>
            <span class="trading_volume">总市值:<strong id="tvalue">276895.2</strong>亿</span>
            <span class="sjl">市净率:<strong id="tvaluep">0</strong></span>
        </li>
        <li>
            <span class="zs">昨收:<strong id="pprice">2535.10</strong></span>
            <span class="trading_volume">流通市值:<strong id="flowvalue">238534.6</strong>亿</span>
            <span class="syl">市盈率(动):<strong id="fvaluep">亏损</strong></span>
        </li>
    </ul>
</div>
  • 4
    点赞
  • 0
    评论
  • 14
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值