【问题标题】:Vim Regex Capture Groups [bau -> byau : ceu -> cyeu]Vim 正则表达式捕获组 [bau -> byau : ceu -> cyeu]
【发布时间】:2013-11-23 00:04:22
【问题描述】:

我有一个单词列表:

bau
ceu
diu
fou
gau

我想把这个列表变成:

byau
cyeu
dyiu
fyou
gyau

我没有成功尝试命令:

:%s/(\w)(\w\w)/\1y\2/g

鉴于这不起作用,我必须更改什么才能使正则表达式捕获组在 Vim 中工作?

【问题讨论】:

  • 这有点跑题了,所以我把它放在这里作为评论但是......我会做:%norm ay<CR>
  • 在你的情况下(如果它与描述的完全一样),它是一个选项:用l移动到第二列,用Ctrl+v进入可视块模式,用Shift+g标记整个列通过l,然后使用Shift+i进入插入模式并输入'y'。 7 次击键,包括完成Esc 以退出插入模式。不作为答案发布,因为它实际上与捕获组无关(这是我在找到这个时搜索的内容)。 :-)

标签: regex vim capturing-group regex-group


【解决方案1】:

解决这个问题的一种方法是确保模式被转义括号括起来:

:%s/\(\w\)\(\w\w\)/\1y\2/g

略短(并且更神奇-al)是使用\v,这意味着在它之后的所有ASCII字符除了'0'-'9''a'-'z''A'-'Z'和@ 987654328@有特殊含义:

:%s/\v(\w)(\w\w)/\1y\2/g

见:

【讨论】:

    【解决方案2】:

    如果您不想用反斜杠转义捕获组(这是您错过的),请在前面添加 \v 以将 Vim 的正则表达式引擎转换为 非常神奇 模式:

    :%s/\v(\w)(\w\w)/\1y\2/g
    

    【讨论】:

    • Ingo,很抱歉把问题放在错误的地方:这工作在:exmode 中找到;有没有办法在 gvim 查找/替换对话框中做到这一点?
    • @JJoao:不,查找/替换框仅用于文字搜索和替换。无论如何,您不应该使用它;它只是记事本用户的训练轮。
    • Ingo,谢谢(这不适合我:我对 exmode 很满意,但适合字典项目中的语言学家合作者):它几乎可以工作 - 使用 \v... regexp 工作查找;在替换字符串中,& 有效,但 \ 受到保护(\1\r 丢失)
    • @JJoao:是的,这也是我在玩它时发现的。我仍然怀疑在没有 Ex 模式的情况下使用 Vim 是否是一个好主意,但您可以通过 inputdialog() 和一些 Vimscript 轻松构建自己的搜索和替换对话框(内部由 :s 提供支持)。
    • Ingo:再次感谢您;我同意你的怀疑意见。 Inputdialg+:s+vimscript 可能是 gvim 的 find replace 的构建方式。对我来说\1 \r 治疗是一个 gvim 错误。我会尝试将它发布在一些 vim 特定的列表中。与此同时,我将尝试我的一个 vimscript-inputdialog。
    【解决方案3】:

    你也可以使用这个更短的模式:

    :%s/^./&y
    
    • %s 将模式应用于整个文件。
    • ^. 匹配该行的第一个字符。
    • &y 在模式后添加y

    【讨论】:

      【解决方案4】:

      您还必须转义 Grouping 括号:

      :%s/\(\w\)\(\w\w\)/\1y\2/g
      

      这就行了。

      【讨论】:

      • 来自 Sublime Text 3,这太可怕了。为什么语法是这样的?转义不是文字的普通文本的字符是没有意义的。
      • @Unknow0059 在这种情况下,括号不是文字。它们是分隔组以保存替换表达式的元字符。正如人们所期望的那样,在表达式中放置一个非转义的括号将匹配文字字符(这就是 OP 的绊脚石)。
      • 我是一个普通的 vim 用户,我也认为这很糟糕。 @Unknow0059
      【解决方案5】:

      非常好!在选择中,使用以下内容(例如):

      :'<,'>s/^\(\w\+ - \w\+\).*/\1/
      

      :'<,'>s/\v^(\w+ - \w+).*/\1/
      

      Space - Commercial - Boeing 解析为Space - Commercial

      解释:

      • ^ : 匹配行首
      • \-escape (, +, ) 每个第一个正则表达式(接受的答案) - 或前面加上 \v(@ingo-karkat 的答案)
      • \w\+ 找到一个词(\w 将找到第一个字符):在这个例子中,我搜索一个词,然后是 -,然后是另一个词)
      • .* 捕获组后需要查找/匹配/排除剩余文本

      附录。 这有点离题,但我建议 Vim 不适合执行更复杂的正则表达式/捕获。 [我正在做类似于以下的事情,这就是我找到这个线程的方式。]

      在这些情况下,最好将这些行转储到文本文件并“就地”编辑 (sed -i ...) 或重定向 (sed ... &gt; out.txt)。

      echo 'Space Sciences - Private Industry - Boeing' | sed -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/'
      Space Sciences - Private Industry 
      
      touch ~/in.txt
      touch ~/out.txt
      
      echo 'Space Sciences - Private Industry - Boeing' > ~/in.txt
      cat in.txt
      Space Sciences - Private Industry - Boeing
      
      sed -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/' ~/in.txt > ~/out.txt
      cat ~/out.txt 
      Space Sciences - Private Industry
      ## Caution: if you forget the > redirect, you'll edit your source.
      
      ## source unaltered:
      cat in.txt
      Space Sciences - Private Industry - Boeing
      
      ## edit in place:
      sed -i -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/' ~/in.txt
      cat in.txt
      Space Sciences - Private Industry 
      

      该表达式sed -r 's/^((\w+ ){1,2}- (\w+ ){1,2}).*/\1/' 允许灵活地查找单词的{x,y} 重复项——参见https://www.gnu.org/software/sed/manual/html_node/Regular-Expressions.html。在这里,由于我的短语由- 分隔,我可以简单地调整这些参数以获得我想要的。

      【讨论】:

        猜你喜欢
        • 2018-11-25
        • 2018-03-11
        • 1970-01-01
        • 1970-01-01
        • 2015-07-24
        • 1970-01-01
        • 2018-09-08
        相关资源
        最近更新 更多