正则表达式提取器_C++11新特性7 - 正则表达式

11b1fa943d08b39403cf562282e50090.png

C++11 新增了正则表达式的标准库支持,本文简介 C++ 正则表达式的使用

在 C++ 中使用正则表达式,和其它语言差别不大

int main() {
  regex e("abc*");
  bool m = regex_search("abccc", e);

  // 输出 yes
  cout << (m ? "yes" : "no") << endl;
}

C++11 自带了 6 种正则表达式语法的支持

  1. ECMAScript
  2. basic
  3. extended
  4. awk
  5. grep
  6. egrep

C++11 默认使用 ECMAScript 语法,这也是 6 种语法中最强大的,假如想使用其他 5 种语法,只需在声明 regex 对象时指定即可

regex e("^a.", regex_constants::grep);

假如我们不仅仅想知道一个正则表达式是否匹配一个字符串,我们还想要提取出匹配的部分,例如我们需要从邮箱中提取用户名和网址,就需要用到 match_results

int main() {
  string str("Email a@bc.com abc");

  // 等同于 match_results<string>
  smatch m; 

  regex e(
    "([[:w:]]+)@([[:w:]]+.com)"
  );
  bool found = regex_search(
    str, m, e
  );

  // m.size=3, 存储了 3 个 result
  cout << "m.size=" 
    << m.size() << endl;

  /* 迭代 match_results, 输出
  m[0]=a@bc.com (整个匹配)
  m[1]=a (第1个group)
  m[2]=bc.com (第2个group)
  */
  for (int n=0; n<m.size(); n++){
    cout << "m[" << n << "]=" 
      << m[n].str() << endl;
  //等价写法 m.str(n), *(m.begin()+n) 
  }
  
  // m.prefix=Email
  cout << "m.prefix=" 
    << m.prefix().str() << endl;
  
  // m.suffix= is mine
  cout << "m.suffix=" 
    << m.suffix().str() << endl;
}

假如我们想要匹配的字符串中,有多个子串都可以匹配正则表达式,并且我们想把这些子串全部找出来,例如一个字符串中包含多个邮箱地址,那么就需要用到 regex_iterator

int main() {
  string str(
    "a@bc.com, d@ef.com, aa@b.com"
  );

  regex e(
    "([[:w:]]+)@([[:w:]]+.com)"
  );

  sregex_iterator pos(
    str.cbegin(), str.cend(), e
  ); // 定义 regex_iteraror
  
  // C++惯例: 默认构造的迭代器表示序列结束
  sregex_iterator end;

/*
email=a@bc.com, user=a, domain=bc.com
email=d@ef.com, user=d, domain=ef.com
email=aa@bb.com, user=aa, domain=b.com
*/
  for (; pos!=end; pos++) {
    cout << "email=" << pos->str(0) 
      << ", user=" << pos->str(1) 
      << ", domain=" << pos->str(2) 
      << endl;
  }
}

如上我们可以看到,regex_iterator 其实就是迭代字符串中所有正则表达式匹配的 match_results

除此之外,C++ 还提供了另一种跌到器, regex_token_iterator。不同的是,regex_token_iterator 迭代的是所有正则表达式匹配中的指定子表达式,或迭代未匹配的子字符串

int main() {
  string str(
    "a@bc.com, d@ef.com, aa@bb.com"
  );

  regex e(
    "([[:w:]]+)@([[:w:]]+.com)"
  );

  sregex_token_iterator pos(
    str.cbegin(), str.cend(), e
  ); // 定义regex_token_iterator
  sregex_token_iterator end; //序列结束
  

  /*
  Matched: a@bc.com
  Matched: d@ef.com
  Matched: aa@bb.com
  */
  for (; pos!=end; pos++) {
    cout << "Matched:  " 
      << *pos << endl;
  }
}

我们可以修改 pos 的定义,使它每次迭代 match_results 的第 2 个 group

// 第 4 个参数表示第几个 group
sregex_token_iterator pos(
  str.cbegin(), str.cend(), e, 2
);

值得注意的是,如果我们把这里的参数设为 -1,则迭代字符串中所有不匹配正则表达式的部分,相当于用正则表达式切割字符串

int main() {
  string str("a bb   cd");

  regex e("s+"); // 匹配空格

  // 迭代不匹配正则表达式的部分
  sregex_token_iterator pos(
    str.cbegin(), str.cend(), e, -1
  );
  sregex_token_iterator end;
  
  /*
  Matched: a
  Matched: bb
  Matched: cd
  */
  for (; pos!=end; pos++) {
    cout << "Matched: " 
      << *pos << endl;
  }
}

正则表达式还有一个常用的场景——字符串替换。C++ 中我们可以使用 regex_replace

int main() {
  string str(
    "a@bc.com, d@ef.com, aa@bb.com"
  );

  regex e(
    "([[:w:]]+)@([[:w:]]+.com)"
  );

  cout << regex_replace(
    str, e, "$1 is on $2"
  );
}

输出为

a is on bc.com, d is on ef.com, aa is on bb.com

本文主要翻译自 Bo Qian 的 YouTube 视频

C++ 11 Library: Regular Expression 1​youtu.be C++ 11 Library: Regular Expression 2 -- Submatch​youtu.be C++ 11 Library: Regular Expression 3 -- Iterators​youtu.be
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值