【问题标题】:Replace string unless between two points替换字符串,除非在两点之间
【发布时间】:2013-04-11 00:04:42
【问题描述】:

我有正则表达式需要用\" 替换所有反斜杠\\,除非\\ 在两个美元符号$\\bar{x}$ 之间。我不知道如何在正则表达式中替换所有这些,除非它介于这两个字符之间。

这是一个字符串和一个gsub,即使在双倍美元内也能摆脱所有\\

x <- c("I like \\the big\\ red \\dog\\ $\\hat + \\bar$, here it is $\\bar{x}$",
    "I have $50 to \\spend\\", "$\\frac{4}{5}$ is nice", "$\\30\\ is nice too") 

gsub("\\\\", "\"", x)

## > gsub("\\\\", "\"", x)
## [1] "I like \"the big\" red \"dog\" $\"hat + \"bar$, here it is $\"bar{x}$" 
## [2] "I have $50 to \"spend\""    
## [3] "$\"frac{4}{5}$ is nice"   
## [4] "$\"30\" is nice too"  

我追求的是:

## [1] "I like \"the big\" red \"dog\" $\\hat + \\bar$, here it is $\\bar{x}$" 
## [2] "I have $50 to \"spend\""
## [3] "$\\frac{4}{5}$ is nice"   
## [4] "$\"30\" is nice too" 

【问题讨论】:

  • 我不认为正则表达式是解决这个问题的正确工具..您可能应该拆分并加入$
  • @ExplosionPills 说了什么。这种语言充其量是上下文无关的,我很确定它是上下文相关的。最大的问题是像"I have $50 to \\spend\\. My sister has $40." 这样的东西有什么合适的?
  • @FrankieTheKneeMan 这是一个我愿意处理的机会。预期目的是获取学术引用。这可能包括数学(而 $$ 是数学的标记方法)。我很少会遇到这样的美元符号的两种用法。
  • @Explosion Pills 我愿意接受我一直在寻找最有效的其他方法。我认为您可能可以像我一样使用gsub,然后查找出现$$"\\$.+?\\$" 但无法连接最后一个点的情况。
  • 我不是 R 天才,但您应该使用 stat.ethz.ch/R-manual/R-patched/library/base/html/strsplit.html 之类的东西来拆分 "$" 上的字符串,然后在每个其他结果片段上运行您现有的 gsub。 (0、2、4 等...)无论如何,您可能还想在最后一块上运行它。然后您应该使用stat.ethz.ch/R-manual/R-patched/library/base/html/paste.html 将它们重新组合在一起。

标签: regex r


【解决方案1】:

使用@FrankieTheKneeMan 的strsplit 方法:

x <- c("I like \\the big\\ red \\dog\\ $\\hat + \\bar$, here it is $\\bar{x}$",
       "I have $50 to \\spend\\",
       "$\\frac{4}{5}$ is nice",
       "$\\30\\ is nice too") 

# > cat(x, sep='\n')
# I like \the big\ red \dog\ $\hat + \bar$, here it is $\bar{x}$
# I have $50 to \spend\
# $\frac{4}{5}$ is nice
# $\30\ is nice too

# split into parts separated by '$'.
# Add a space at the end of every string to deal with '$'
#  at the end of the string (as
#      strsplit('a$', '$', fixed=T)
#  is just 'a' in R)
bits <- strsplit(paste(x, ''), '$', fixed=T)

# apply the regex to every second part (starting with the first)
# and always to the last bit (because of the ' ' we added)
out <- sapply(bits, function (x) {
                   idx <- unique(c(seq(1, length(x), by=2), length(x)))
                   x[idx] <- gsub('\\', '\"', x[idx], fixed=T)
                   # join back together
                   x <- paste(x, collapse='$')
                   # remove that last ' ' we added
                   substring(x, 1, nchar(x) - 1)
               }, USE.NAMES=F)

# > cat(out, sep='\n')
# I like "the big" red "dog" $\hat + \bar$, here it is $\bar{x}$
# I have $50 to "spend"
# $\frac{4}{5}$ is nice
# $"30" is nice too

这总是会出现失败的情况 ("I have $20. \\hi\\ Now I have $30"),因此您必须牢记这一点,并针对您期望的其他格式的字符串对其进行测试。

【讨论】:

  • 哇,我尝试了所有方法来使弗兰基的方法奏效。谢谢数学咖啡。我会稍微研究一下并接受。我认为正则表达式可能比我预期的要困难。
  • 可以修补我的方法以使其适用于"I have $20. \\hi\\ Now I have $30",但它会变得非常难以维护。
  • @mathematical.coffee 谢谢我认为这是一个简单的正则表达式。不是这样。效果很好。 +1
【解决方案2】:

如果您忽略内容相关问题,则可以使用 PCRE 正则表达式进行替换。 (如果$ 不表示要保留\ 的部分具有明确的形式,则可以逐个进行修补。

假设$ 总是开始和结束一个非替换区域,除了字符串中最后一个奇数$ 的情况。

模式(第一行是RAW正则表达式,第二行是引号字符串文字):

\G((?:[^$\\]|\$[^$]*+\$|\$(?![^$]*+\$))*+)\\
"\\G((?:[^$\\\\]|\\$[^$]*+\\$|\\$(?![^$]*+\\$))*+)\\\\"

替换字符串:

\1"
"\\1\""

DEMO 1
DEMO 2

说明

这个想法是在不包含在 2 个$ 中的字符串中找到下一个\。这是通过确保匹配总是从最后一个匹配停止的地方开始\G 来实现的,以确保我们不会跳过任何文字 $ 并匹配内部的 \

我们不会替换 3 种形式的序列:

  • 既不是文字 $ 也不是文字 \: [^$\\]
  • 2 $ 之间的任何文本(这不考虑转义机制,如果有的话):\$[^$]*+\$
  • 允许在奇数最后一个$ 之后替换\\$(?![^$]*+\$)

所以我们只需遍历上述 3 种形式的序列的任意组合,并匹配最近的 \ 进行替换。

与上述相同的假设,除了$&lt;digit&gt; 不会启动非替换区域。

即使使用这种字符串也可以:

我有 50 美元要 \spend\。我只是 $\bar$ 记得我上次的 \paycheck\ 中还有 30 美元 $\left$。孤独的$ \在最后\

图案:

\G((?:[^$\\]|\$\d|\$(?![^$]*\$)|\$[^$]*+\$)*+)\\
"\\G((?:[^$\\\\]|\\$\\d|\\$(?![^$]*\\$)|\\$[^$]*+\\$)*+)\\\\"

DEMO

\$\d 交替添加到\$[^$]*+\$ 前面,以使引擎首先检查该情况。

【讨论】:

  • 看起来很有希望,但无法与 R 一起使用:invalid regular expression '\G((?:[^$\\]|\$[^$]*+\$)*)\\', reason 'Invalid use of repetition operators'
  • @TylerRinker:你需要启用perl=TRUEstat.ethz.ch/R-manual/R-patched/library/base/html/regex.html
  • @TylerRinker:做了一点改动。请使用第 2 行。第一行是显示正则表达式的实际形式。
  • 这可能是 R 的事情,但结果有很多美元符号,正如您在我上面的 EDIT 2 中看到的那样
  • @TylerRinker:没关系。我也没有信心能维持这个烂摊子。
猜你喜欢
  • 2011-04-14
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多