如何解决正则表达式仅用于替换括号外的特定字符
我正在寻找正则表达式(最好在 R
中),它可以替换(任意数量的)特定字符说 ;
说 ;;
但仅当 不存在时 内括号 ()
内的文本字符串。
注意:1. 括号内也可能有多个替换字符
2.数据/向量中没有嵌套括号
示例
-
text;othertext
替换为text;;othertext
- 但
text;other(texttt;some;someother);more
将替换为text;;other(texttt;some;someother);;more
。 (即;
仅在()
之外被替换文本替换)
如果需要澄清,我会尽量解释
in_vec <- c("abcd;ghi;dfsF(adffg;adfsasdf);dfg;(asd;fdsg);ag","zvc;dfasdf;asdga;asd(asd;hsfd)","adsg;(asdg;ASF;DFG;ASDF;);sdafdf","asagf;(fafgf;sadg;sdag;a;gddfg;fd)gsfg;sdfa")
in_vec
#> [1] "abcd;ghi;dfsF(adffg;adfsasdf);dfg;(asd;fdsg);ag"
#> [2] "zvc;dfasdf;asdga;asd(asd;hsfd)"
#> [3] "adsg;(asdg;ASF;DFG;ASDF;);sdafdf"
#> [4] "asagf;(fafgf;sadg;sdag;a;gddfg;fd)gsfg;sdfa"
预期输出(手动计算)
[1] "abcd;;ghi;;dfsF(adffg;adfsasdf);;dfg;;(asd;fdsg);;ag"
[2] "zvc;;dfasdf;;asdga;;asd(asd;hsfd)"
[3] "adsg;;(asdg;ASF;DFG;ASDF;);;sdafdf"
[4] "asagf;;(fafgf;sadg;sdag;a;gddfg;fd)gsfg;;sdfa"
解决方法
虽然这个问题可以用正则表达式解决,但使用一个简单的函数可能更直接、更容易理解。
replace_semicolons_outside_parentheses <- function(raw_string) {
"""Replace ; with ;; outside of parentheses"""
processed_string <- ""
n_open_parentheses <- 0
# Loops over characters in raw_string
for (char in strsplit(raw_string,"")[[1]]) {
# Update the net number of open parentheses
if (char == "(") {
n_open_parentheses <- n_open_parentheses + 1
} else if (char == ")") {
n_open_parentheses <- n_open_parentheses - 1
}
# Replace ; with ;; outside of parentheses
if (char == ";" && n_open_parentheses == 0) {
processed_string <- paste0(processed_string,";;")
} else {
processed_string <- paste0(processed_string,char)
}
}
return(processed_string)
}
请注意,上面的函数也适用于嵌套括号:嵌套括号内的分号不会被替换!可以在一行中获得所需的输出:
out_vec <- lapply(in_vec,replace_semicolons_outside_parentheses)
# 1. 'abcd;;ghi;;dfsF(adffg;adfsasdf);;dfg;;(asd;fdsg);;ag'
# 2. 'zvc;;dfasdf;;asdga;;asd(asd;hsfd)'
# 3. 'adsg;;(asdg;ASF;DFG;ASDF;);;sdafdf'
# 4. 'asagf;;(fafgf;sadg;sdag;a;gddfg;fd)gsfg;;sdfa'
,
您可以像这样使用 gregexpr
和 regmatches
:
x <- gregexpr("\\(.*?\\)",in_vec) #Find the part between ( and )
mapply(function(a,b) {
paste(matrix(c(gsub(";",";;",b),a,""),2,byrow=TRUE),collapse = "")
},regmatches(in_vec,x),x,TRUE))
#[1] "abcd;;dfsF(adffg;adfsasdf);;dfg;;(asd;fdsg);;ag"
#[2] "zvc;;dfasdf;;asdga;;asd(asd;hsfd)"
#[3] "adsg;;(asdg;ASF;DFG;ASDF;);;sdafdf"
#[4] "asagf;;(fafgf;sadg;sdag;a;gddfg;fd)gsfg;;sdfa"
但它仅适用于简单的打开 (
关闭 )
组合。
并且只使用一个 gsub
:
gsub(";(?=[^)]*($|\\())",in_vec,perl=TRUE)
#[1] "abcd;;dfsF(adffg;adfsasdf);;dfg;;(asd;fdsg);;ag"
#[2] "zvc;;dfasdf;;asdga;;asd(asd;hsfd)"
#[3] "adsg;;(asdg;ASF;DFG;ASDF;);;sdafdf"
#[4] "asagf;;(fafgf;sadg;sdag;a;gddfg;fd)gsfg;;sdfa"
;
找到 ;
,(?=)
.. Positive Lookahead,[^)]
.. 除了 )
之外的所有内容,*
重复前面的 0到 n 次,($|\\()
.. 匹配结束 $
或 (
。
或者:
gsub(";(?![^(]*\\))",perl=TRUE)
;
找到 ;
,(?!)
.. Negative Lookahead,[^()]
.. 除了 (
之外的所有内容,*
重复前面的 0到 n 次,\\)
.. 流经 )
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。