微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正则表达式仅用于替换括号外的特定字符

如何解决正则表达式仅用于替换括号外的特定字符

我正在寻找正则表达式(最好在 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'
,

您可以像这样使用 gregexprregmatches

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 举报,一经查实,本站将立刻删除。