【问题标题】:R: Remove dots in text but not those marking decimal pointsR:删除文本中的点,但不删除那些标记小数点的点
【发布时间】:2017-10-10 22:55:48
【问题描述】:

我是正则表达式的新手,所以请多多包涵。

我有一个这样的字符串:

txt1 <- 'a,b,a.b,a.,1,2,1.2,1.,.,11,222,11.222,11.'

假设它来自 .csv,每个单元格都用“,”分隔。现在我想删除所有的“。”除了那些标记小数点。最后,我想得到这样的结果:

txt2 <- 'a,b,ab,a,1,2,1.2,1,,11,222,11.222,11'

我尝试了以下代码:

txt2 <- gsub(pattern = '[^a-z0-9,(\\d\\.\\d)]', replacement = '', text = txt1)
txt2 <- gsub(pattern = '[^a-z0-9,|(\\d\\.\\d)]', replacement = '', text = txt1)

但两者都不起作用,都返回

> print(txt2)
[1] "a,b,a.b,a.,1,2,1.2,1.,.,11,222,11.222,11."

知道如何更正我的代码吗?谢谢!

【问题讨论】:

    标签: r regex string gsub


    【解决方案1】:

    关键是使用负向向后看?&lt;!和负向向前看?!

    > txt1 <- 'a,b,a.b,a.,1,2,1.2,1.,.,11,222,11.222,11.'
    > txt2 <- gsub(pattern='((?<![0-9])\\.)|(\\.(?![0-9]))', replacement='', x=txt1, perl=TRUE)
    > txt2
    [1] "a,b,ab,a,1,2,1.2,1,,11,222,11.222,11"
    

    此模式匹配句点\\.,该句点前面有一个不是0-9 的字符,或者一个句点后面跟着一个不是0-9 的字符。您必须设置 perl=TRUE 才能让 R 识别后视和前瞻。

    这将修剪前导句点字符,因此“.2”将变为“2”。如果不希望这样做,则需要向后查找(?&lt;![0-9,])

    【讨论】:

    • 这里将\.放入捕获组的目的是什么?
    • 无需后顾之忧,看上面两个答案。
    • 非常感谢您的详细解释。很有帮助!
    • @CAustin 我编辑了捕获组 - 结果你不需要它。 @MauritsEvers 向后看是为了排除像'A.2'和'.2'这样的值(看起来OP想要修剪句点字符)。如果 OP 想要保留前导句点字符,例如在 '.2' 中,则后视应该是 (?&lt;![0-9,])
    【解决方案2】:

    您可以使用负前瞻。匹配 \.(?!\d) 并将其替换为空。

    https://regex101.com/r/LNHYOY/1

    【讨论】:

    • 非常感谢您的回答。该链接非常有用!
    • 这是一个后续问题,希望您也能回答。由于括号() 在列表[] 中无法识别,我如何编码以识别不在组中的内容? (?!(the group)) 是唯一的方法吗?
    • 您是否在谈论一种否定整个字符串的方法,类似于 [^abc] 如何否定单个字符 a、b 和 c?没有办法完全重现工作方式,但是可以使用负前瞻(使用(?! ... ),如上面的答案)来实现接近的目标。
    • 我明白了。再次感谢您的热心帮助!
    【解决方案3】:

    Negative lookahead(正如@CAustin 所建议的)似乎是最优雅和简洁的。

    由于上述解决方案都没有为您提供实际的 R 代码,因此这里是:

    txt2 <- gsub("\\.(?!\\d)", "", txt1, perl = TRUE)
    [1] "a,b,ab,a,1,2,1.2,1,,11,222,11.222,11"
    

    【讨论】:

      猜你喜欢
      • 2019-02-28
      • 2020-03-05
      • 2014-10-15
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多