👇 连享会 · 推文导航 |
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 ]
中的其它选项包括:
insensitive
:启用不区分大小写的匹配。
comments
:允许在正则表达式中使用空格和注释。
dotall
:启用 Dotall 模式,该模式下,元字符
.
可以匹配任意单个字符,包括换行符和回车符。
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. 结语