【问题标题】:How to trim and replace a string如何修剪和替换字符串
【发布时间】:2013-09-03 08:23:34
【问题描述】:
string<-c("       this is a string  ")

是否可以在字符串的两侧(或根据需要仅在一侧)修剪掉空格并将其替换为所需的字符,例如 R 中的这个?字符串两边的空格数不同,替换时必须保留。

"~~~~~~~this is a string~~"

【问题讨论】:

    标签: regex string r


    【解决方案1】:

    这似乎是一种低效的方法,但也许你应该关注gregexprregmatches 而不是gsub

    x <- "    this is a string  "
    pattern <- "^ +?\\b|\\b? +$"
    startstop <- gsub(" ", "~", regmatches(x, gregexpr(pattern, x))[[1]])
    text <- paste(regmatches(x, gregexpr(pattern, x), invert=TRUE)[[1]], collapse="")
    paste0(startstop[1], text, startstop[2])
    # [1] "~~~~this is a string~~"
    

    而且,为了好玩,作为一个函数,以及一个“矢量化”函数:

    ## The function
    replaceEnds <- function(string) {
      pattern <- "^ +?\\b|\\b? +$"
      startstop <- gsub(" ", "~", regmatches(string, gregexpr(pattern, string))[[1]])
      text <- paste(regmatches(string, gregexpr(pattern, string), invert = TRUE)[[1]],
                    collapse = "")
      paste0(startstop[1], text, startstop[2])
    }
    
    ## use Vectorize here if you want to apply over a vector
    vReplaceEnds <- Vectorize(replaceEnds)
    

    一些样本数据:

    myStrings <- c("    Four at the start, 2 at the end  ", 
                   "   three at the start, one at the end ")
    
    vReplaceEnds(myStrings)
    #        Four at the start, 2 at the end        three at the start, one at the end  
    #  "~~~~Four at the start, 2 at the end~~" "~~~three at the start, one at the end~"
    

    【讨论】:

    • 我的实际数据确实需要“矢量化”。非常感谢。
    • @jackson,您也可以使用相同的方法来“矢量化”Andrie 的函数。
    • @jackson gsub 矢量化了吗?
    • @SimonO101,是的——我敢肯定你的蛋糕很受欢迎。
    • @SimonO101 没有注意到。您有效地一口气拥有了这一切。
    【解决方案2】:

    使用gsub:

    gsub(" ", "~", "    this is a string  ")
    [1] "~~~~this~is~a~string~~"
    

    此函数使用正则表达式替换(即 sub)字符串中所有出现的模式。

    在你的情况下,你必须用一种特殊的方式来表达模式:

    gsub("(^ *)|( *$)", "~~~", "    this is a string  ")
    [1] "~~~this is a string~~~"
    

    图案的意思:

    • (^ *):在字符串的开始处找到一个或多个空格
    • ( *$):在字符串的结尾找到一个或多个空格
    • `|: OR 运算符

    现在您可以使用这种方法来解决用新字符替换每个空格的问题:

    txt <- "    this is a string  "
    foo <- function(x, new="~"){
      lead <- gsub("(^ *).*", "\\1", x)
      last <- gsub(".*?( *$)", "\\1", x)
      mid  <- gsub("(^ *)|( *$)", "", x)
      paste0(
        gsub(" ", new, lead),
        mid,
        gsub(" ", new, last)
      )
    }
    
    > foo("    this is a string  ")
    [1] "~~~~this is a string~~"
    
    > foo(" And another one        ")
    [1] "~And another one~~~~~~~~"
    

    如需了解更多信息,请参阅?gsub?regexp

    【讨论】:

    • 这也会在单词之间添加~。
    • 原字符串两端的空格不对称。
    • 问题中未明确描述,但似乎前导和滞后空白的长度可能不同,应替换为适当数量的 ~
    • 对不起,这个问题漏掉了一个关键点。 replacer(~) 的数量必须与字符串两侧替换的空格的数量相同。我正在编辑问题。感谢 cmets。
    • 我认为这会比我的解决方案更快。
    【解决方案3】:

    或者使用更复杂的模式匹配和gsub...

    gsub("\\s(?!\\b)|(?<=\\s)\\s(?=\\b)", "~", "    this is a string  " , perl = TRUE )
    #[1] "~~~~this is a string~~"
    

    或者用@AnandaMahto 的数据:

    gsub("\\s(?!\\b)|(?<=\\s)\\s(?=\\b)", "~", myStrings , perl = TRUE )
    #[1] "~~~~Four at the start, 2 at the end~~" 
    #[2] "~~~three at the start, one at the end~"
    

    说明

    这使用了正负前瞻和后瞻断言:

    • \\s(?!\\b) - 匹配一个空格,\\s 后面没有单词边界,(?!\\b)。这对于除了第一个单词之前的最后一个空格之外的所有内容都可以单独工作,即我们自己会得到
      "~~~~ this is a string~~"。所以我们需要另一种模式......

    • (?&lt;=\\s)\\s(?=\\b) - 匹配一个空格,\\s 前面是另一个空格,(?&lt;=\\s) 后跟一个单词边界,@ 987654331@.

    它是gsub,所以它会尝试尽可能多地进行匹配。

    【讨论】:

    • 你的正则表达式技能远远超过我。 +1
    • @AnandaMahto 我很确定我从你那里学到了断言! :-)
    猜你喜欢
    • 2018-12-04
    • 2013-08-24
    • 1970-01-01
    • 2017-09-20
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 2022-06-22
    • 2013-10-21
    相关资源
    最近更新 更多