在 Ruby gsub 中用通配符删除单引号之间的所有内容

Remove everything between single quotes with wildcard in Ruby gsub

试图了解如何为此转义一切。我试图在文件中查找并替换此实例,set :repo_url, '' 但单引号之间可能有任意数量的字符。

我需要替换的一行示例是:

set :repo_url, 'git://github.com/something.com.git'

我已经尝试过以下方法:

contents.gsub!("set :repo_url, /^\'(.*)\'$/", "set :repo_url, 'test'") 
contents.gsub!("set :repo_url, /^'(.*)'$/", "set :repo_url, 'test'")
contents.gsub!("set :repo_url, '(.*)", "set :repo_url, 'test'")

None 的那些工作,但只有当引号之间没有任何内容时才这样做:

contents.gsub!("set :repo_url, ''", "set :repo_url, 'test'")

我错过了什么?抱歉,我还在学习 Ruby + 正则表达式。

contents.gsub!(/^set :repo_url, '.*?'$/, "set :repo_url, 'test'")

应该做你想做的事

TL;DR

有不止一种方法可以满足您的需求,包括使用特殊语法修复引号问题以及操纵匹配变量来控制将被替换的文本。

使用以下应该有效:

contents.gsub!(
  /^set :repo_url[^'"]+\K(.).*?/,
  'https://example.com/foo.git'
)

下面详细解释了它的工作方式。

一个带输出的实例

如果您想做的只是避免引号问题,您可以对字符串使用 Ruby 的 %q() 语法以避免必须转义引号。但是,如果您在匹配时遇到其他问题,您可以创建更强大的正则表达式,如 /^set :repo_url[^'"]+\K(.).*?/。例如:

    contents = <<~EOF
      set :repo_url, 'git://github.com/foo/bar.git'
      set :repo_url, 'git://github.com/foo/baz.git' # a comment
      set :repo_url, "git://github.com/foo/bar.git" # using doublequotes
    EOF
    
    contents.gsub!(
      /^set :repo_url[^'"]+\K(.).*?/,
      'https://example.com/foo.git'
    )

   puts contents

这将打印:

set :repo_url, 'https://example.com/foo.git'  
set :repo_url, 'https://example.com/foo.git' # a comment  
set :repo_url, "https://example.com/foo.git" # using doublequotes  
#=> nil

了解正则表达式模式

String#gsub 和相关方法通过用替换文本替换存储在 $& 中的匹配项来工作,因此您可以通过管理存储的内容来做很多有趣的事情(或不)在匹配和关联的捕获组中。正则表达式模式的工作原理如下:

  1. ^set :repo_url

    只匹配每行开头的固定字符串“set :repo_url”。

  2. [^'"]+

    匹配所有非引号字符。

  3. \K

    使用未记录的“保留”标志丢弃 $& 左侧的内容,防止它被替换文本破坏。

  4. (.)

    捕获使用的引号字符,例如"'。将引号存储在 $& 和 $1 中。

  5. .*?

    非贪婪匹配将所有字符添加到 $&.

了解替换字符串

替换字符串利用正则表达式模式中的捕获组来恢复字符串的部分,否则这些部分将被 String#gsub!方法。它是这样工作的:

  1. </code></p> <p>将捕获组 1 中的引号字符添加到替换字符串中。</p> </li> <li><p><code>https://example.com/foo.git

    这是您要替换其他 URL 的实际文本。

  2. </code></p> <p>再次将捕获组 1 中的相同引号字符添加到替换字符串的末尾。</p> </li> </ol> <p>因为 <code>\K 左边和结束引号右边的所有内容都没有通过我们的正则表达式存储在 $& 中,所以我们没有使用捕获组或反向引用将行的那些部分包含到我们的替换字符串中。当然还有其他方式来表示匹配或替换,但这对于已发布的示例非常有效。