专栏名称: 连享会
连玉君老师团队分享,主页:lianxh.cn。白话计量,代码实操;学术路上,与君同行。
目录
相关文章推荐
直播海南  ·  警惕!广东爆发2起,均在学校! ·  昨天  
直播海南  ·  蒋超良被查! ·  2 天前  
直播海南  ·  大桥通车1年多开裂?官方通报 ·  2 天前  
直播海南  ·  事关电动自行车以旧换新补贴!最新提醒→ ·  3 天前  
51好读  ›  专栏  ›  连享会

jregex:用正则表达式快速实现匹配和替换

连享会  · 公众号  ·  · 2025-02-20 22:00

正文



👇 连享会 · 推文导航 | www.lianxh.cn

图片
图片

温馨提示: 文中链接在微信中无法生效。请点击底部 「阅读原文」 。或直接长按/扫描如下二维码,直达原文:

作者: 汪京 (兰州大学)
邮箱: [email protected]

1. 引言

正则匹配与正则替换是数据清洗或文本分析工作中的重要组成部分, Stata 中的一些命令 ( regexm regexs regexr ustrregexm ustrregexs 等 ) 可以虽然完成这些工作,但这些命令仍有局限,例如不支持 Dotall 模式,这会给正则匹配与替换带来许多不便。William Buchanan 开发了 jregex 命令,该命令与 Stata 中的本机正则表达式函数不同,使用 Java 中提供的正则表达式功能。该命令和 Stata 中的本机函数工作方式之间的最大区别是能够使用 POSIX 字符类 ( 例如:\p{Alpha}, \p{Punct}, 等等)、Dotall 模式以及 Java 中提供的其他一些功能。Pattern API Javadocs 中包括有关Java实现正则表达式的更多信息。下文将介绍 jregex 命令,并给出几个范例。

2. 命令安装

本外部命令的发布者将安装包上传到了 Github ,我们可以在 Stata 中输入以下命令来安装 jregex

** 从 Github 安装命令
net install jregex, from("http://wbuchanan.github.io/StataRegex/")

安装完成后,可以输入 help jregex 查看具体用法。

3. 命令介绍

jregex 是一个基于 Java 的插件,用于 Stata 中的正则表达式。 jregex 命令可以实现 Stata 与 Java 的交互,通过 Stata 调用 Java 中的正则表达式。 jregex 的语法结构如下:

其中,

  • subcommand 为子命令,目前 jregex 只支持 replace 一种子命令,代表正则替换命令;
  • varnameexisting string variable 为数据中的字符串变量名;
  • newvarto store altered values 为正则替换后新生成的变量名,如不指定此参数,则执行正则替换后会覆盖原变量;
  • pattern(string) 为匹配文本使用的正则表达式。可用的正则表达式请查阅此 Java 官方文档,或如下连享会推文:
    • 孙晓艺, 2024, 文本分析:正则表达式之位置匹配, 连享会 No.1350.
    • 梁淑珍, 2022, Stata:正则表达式教程, 连享会 No.968.
    • 游万海, 2020, Stata: 正则表达式和文本分析, 连享会 No.35.
    • 连享会, 2020, 在 Visual Studio (vsCode) 中使用正则表达式, 连享会 No.10.
    • 连享会, 2020, 正则表达式语言 - 快速参考, 连享会 No.81.

[ options ] 中的其它选项包括:

  • canon :启用正则等价。
  • insensitive :启用不区分大小写的匹配。
  • comments :允许在正则表达式中使用空格和注释。
  • dotall :启用 Dotall 模式,该模式下,元字符 . 可以匹配任意单个字符,包括换行符和回车符。
  • literal :启用正则表达式的文本解析。
  • multiline :启用 multiline 模式,该模式下,即使正则表达式里出现了 ^ $ ,也会匹配所有行。
  • unicase :启用此模式时,当 insensitive 模式启用时,将以与 Unicode 标准一致的方式进行不区分大小写的匹配。默认情况下,不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。
  • uniclass :启用 Predefined 字符类和 POSIX 字符类的 Unicode 版本。
  • unixlines :启用 Unix lines 模式。
  • noanchor :对 Matcher类对象 使用透明边界而不是锚定边界。
  • replace(string) :用来替代匹配值的字符串。
  • repfirst :指定该选项后,仅替换第一个匹配值。

4. 使用范例

下面介绍几个使用 jregex 命令进行正则匹配与正则替换的范例:

首先,导入字符串作为范例:

** 导入字符串变量,命名为 addy
input str55 addy
"6675,+Old+Canton+RD,+Ridgeland,+MS,+39157"
"12313,+33RD+Ave+Nort,+SEATTLE,+wa,+98125"
"310,+Cahir+StreeT,+Providence,+Rhode+Island,+02903"
"22,+Oaklawn+Ave,+Cranston,+RI,+02920"
"61,+pine+st,+Attleboro,+MA,+02703"
"10,+larkspur+R0ad,+Warwick,+ri,+02886"
"91,+FaLLon+Ave,+Providence,+RI,+02908"
"195,+Arlington+AVE,+Providence,+RI,+02906"
"74,+REGENT+aVenuE,+Providence,+RI,+02908"
end

4.1 使用正则表达式替换字符串,并覆盖原变量

在 Stata 中输入以下代码,可以将 addy 变量下各字符串中出现的第一个 + 替换为 _this is a replacement string_

** 使用jregex命令进行正则替换
jregex replace addy, repf ///
p(`"\+"') ///
rep(`"_this is a replacement string_"')

** 查看正则替换后的结果
list

+--------------------------------------------------------------------------------+
| addy |
|--------------------------------------------------------------------------------|
1. | 6675,_this is a replacement string_Old+Canton+RD,+Ridgeland,+MS,+39157 |
2. | 12313,_this is a replacement string_33RD+Ave+Nort,+SEATTLE,+wa,+98125 |
3. | 310,_this is a replacement string_Cahir+StreeT,+Providence,+Rhode+Island,+02.. |
4. | 22,_this is a replacement string_Oaklawn+Ave,+Cranston,+RI,+02920 |
5. | 61,_this is a replacement string_pine+st,+Attleboro,+MA,+02703 |
|--------------------------------------------------------------------------------|
6. | 10,_this is a replacement string_larkspur+R0ad,+Warwick,+ri,+02886 |
7. | 91,_this is a replacement string_FaLLon+Ave,+Providence,+RI,+02908 |
8. | 195,_this is a replacement string_Arlington+AVE,+Providence,+RI,+02906 |
9. | 74,_this is a replacement string_REGENT+aVenuE,+Providence,+RI,+02908 |
+--------------------------------------------------------------------------------+

4.2 使用正则表达式替换字符串,并另存为新变量

在 Stata 中输入以下代码,可以将 addy 变量下各字符串中的 _this is a replacement string_ 替换为 + ,并将替换结果另存为 newaddy 变量。

** 使用jregex命令进行正则替换
jregex replace addy newaddy, p(`"_this is a replacement string_"') rep(`"\+"')
** 查看正则替换后的结果
list newaddy

+----------------------------------------------------+
| newaddy |
|----------------------------------------------------|
1. | 6675,+Old+Canton+RD,+Ridgeland,+MS,+39157 |
2. | 12313,+33RD+Ave+Nort,+SEATTLE,+wa,+98125 |
3. | 310,+Cahir+StreeT,+Providence,+Rhode+Island,+02903 |
4. | 22,+Oaklawn+Ave,+Cranston,+RI,+02920 |
5. | 61,+pine+st,+Attleboro,+MA,+02703 |
|----------------------------------------------------|
6. | 10,+larkspur+R0ad,+Warwick,+ri,+02886 |
7. | 91,+FaLLon+Ave,+Providence,+RI,+02908 |
8. | 195,+Arlington+AVE,+Providence,+RI,+02906 |
9. | 74,+REGENT+aVenuE,+Providence,+RI,+02908 |
+----------------------------------------------------+

4.3 使用 POSIX 字符类正则表达式替换字符串

在 Stata 中输入以下代码,可以将 newaddy 变量下各字符串中的每个标点符号替换为一个空格。

** 使用jregex命令进行正则替换
jregex replace newaddy, p(`"\p{Punct}"') rep(" ")
** 查看正则替换后的结果
list newaddy

+----------------------------------------------------+
| newaddy |
|----------------------------------------------------|
1. | 6675 Old Canton RD Ridgeland MS 39157 |
2. | 12313 33RD Ave Nort SEATTLE wa 98125 |
3. | 310 Cahir StreeT Providence Rhode Island 02903 |
4. | 22 Oaklawn Ave Cranston RI 02920 |
5. | 61 pine st Attleboro MA 02703 |
|----------------------------------------------------|
6. | 10 larkspur R0ad Warwick ri 02886 |
7. | 91 FaLLon Ave Providence RI 02908 |
8. | 195 Arlington AVE Providence RI 02906 |
9. | 74 REGENT aVenuE Providence RI 02908 |
+----------------------------------------------------+

4.4 使用 Dotall 模式正则表达式替换回车符和换行符

正如前文中提到的,默认情况下,元字符 . 不会匹配换行符和回车符,设置了 Dotall 模式后,其就会匹配所有字符包括换行符和回车符。但是 Stata 中的几个正则表达式字符串函数 ( regexm regexs regexr ustrregexm ustrregexs 等 ) 是不能使用 Dotall 模式的。此时, jregex 可以用 Dotall 模式很好地解决这个问题。

与前几个范例不同是的,本例需要重新构造字符串。在 Stata 中输入以下代码,可以在当前工作环境下创建新文本文件 "123.txt" 用于储存范例字符串。

** 在当前工作环境下创建新文本文件"123.txt"用于储存范例字符串
file open myfile using "123.txt", write replace
file write myfile `"
"' _n
file write myfile `"
"' _n
file write myfile `"
"' _n
file write myfile `"连享会"' _n
file write myfile `"lianxh
"' _n
file write myfile `"
"' _n
file write myfile `"
"'
file close myfile

在 Stata 中输入以下代码,将字符串导入 Stata 数据中,并储存在变量 str 中。可以看到,此时的 str 中存在空格、换行符与回车符,并且 连享会lianxh 字符被

 包围。假设我们想从此字符串中提取出 连享会lianxh 。首先,尝试使用 ustrregexra 进行正则替换,结果显示替换并不成功。

** 导入并查看字符串
clear
set more off
set obs 1
gen str = fileread("123.txt")
list
** 使用 ustrregexra 进行正则替换
replace str = ustrregexra(str,".+
","")
replace str = ustrregexra(str,"
.+","")
list
     +-------------------------------------------+
| str |
|-------------------------------------------|
1. |



连.. |
+-------------------------------------------+

+-------------------------------------------+
| str |
|-------------------------------------------|
1. |



连享会
lianxh
.. |
+-------------------------------------------+

接下来,重新导入字符串范例,使用 jregex 进行正则替换,并指定 Dotall 模式。结果显示,目标被成功提取出来。

** 重新字符串
clear
set more off
set obs 1
gen str = fileread("123.txt")
** 使用 jregex 进行正则替换
jregex replace str ,p(".+
") rep("") dotall
jregex replace str ,p("
.+") rep("") dotall
jregex replace str ,p("\r\n") rep("")
compress
list
     +---------------+
| str |
|---------------|
1. | 连享会lianxh |
+---------------+

5. 结语







请到「今天看啥」查看全文