【问题标题】:Replacing spaces with underscores within quotes用引号内的下划线替换空格
【发布时间】:2018-06-11 08:41:30
【问题描述】:

我需要用相同的字符串替换大型文本文件中的所有匹配项,例如 'yw234DV w-23-sDf wef23s-d-f',但用下划线代替引号内的所有空格,而不用下划线替换引号外的任何空格。

我正在尝试在 vim 中找到替代解决方案,但也非常感谢 sed 解决方案。每个引号分隔的字符串中的标记数量可能会有所不同。

我一直在 vim 中使用一些正则表达式,但它们非常初级,似乎缺少我需要的东西。

我目前的尝试:

%s/'{[:alnum:] }*/'\0\_/g

我正在尝试对此的变化。

这与我的问题最相似,尽管它是 Java: Replacing spaces within quotes

示例输入:

'wiUEF7-gvouw ow wo24-RTeih we', 'yt23IT iug-76'    

样本输出:

'wiUEF7-gvouw_ow_wo24-RTeih_we', 'yt23IT_iug-76'

【问题讨论】:

  • 您想用下划线替换 any 单引号字符串中的 all 空格吗?或者,还有其他限制吗?
  • 另外,请展示您迄今为止尝试过的内容并描述失败的原因。没有表现出你的努力,人们会认为你是在要求免费咨询,而这里的很多人不喜欢这样。
  • 请显示正确的示例 Input_file 以及正确的示例预期输出(除了 John1024 也要求的内容)。
  • 谢谢我已经编辑了这个问题。我只是阻止了 vim 中的尝试......

标签: regex vim sed substitution


【解决方案1】:

你可以用 VIM 试试这个,在 Macvim 上试试这个:

%s/\%('[^']*'\)*\('[^']*'\)/\=substitute(submatch(1), ' ', '_', 'g')/g

更简单的解决方案,感谢@SergioAraujo:

@%s/\v%(('[^']*'))/\=substitute(submatch(1),' ', '_', 'g')/g

但不确定,如果以下是您所期望的结果 输出:

'wiUEF7-gvouw_ow_wo24-RTeih_we', 'yt23IT_iug-76'

【讨论】:

  • 是否可以在这个解决方案中使用非常神奇的方法来使其更具可读性?
  • @SergioAraujo %s/\v%('[^']*')*('[^']*')/\=substitute(submatch(1), ' ', '_', 'g')/g
  • 一旦我们在正则表达式匹配中有两次相同的模式,我们就可以对它进行分组,不是吗? %s/\v%(('[^']*'))/\=substitute(submatch(1),' ', '_', 'g')/g
  • @SergioAraujo,谢谢 它确实并且可能总是有效
【解决方案2】:

有了这个输入文件:

$ cat file
'wiUEF7-gvouw ow wo24-RTeih we', 'yt23IT iug-76'  

我们可以将单引号内的所有空格转换为下划线:

$ sed -E ":a; s/^(([^']*'[^']*')*[^']*'[^']*)[[:space:]]/\1_/; ta" file
'wiUEF7-gvouw_ow_wo24-RTeih_we', 'yt23IT_iug-76'  

工作原理

  1. :a

    这会创建一个标签a

  2. s/^(([^']*'[^']*')*[^']*'[^']*)[[:space:]]/\1_/

    这会在我们想要的位置插入下划线。

    • ^(([^']*'[^']*')*[^']*'[^']*)[[:space:]]

      这会查找任意奇数个单引号,后跟任意数量的非引号字符,后跟一个空格。该空间之前的所有内容都保存在第 1 组中。

    • \1_

      这会将匹配的文本替换为第 1 组,后跟一个下划线。

  3. ta

    如果前面的命令在字符串中添加了新的下划线,则跳回标签a 并重试。

【讨论】:

    【解决方案3】:

    gnu awk 中使用FPAT 变量,您可以这样做:

    awk -v OFS=', ' -v FPAT="'[^']*'" '{for (h=1; h<=NF; h++) 
    {gsub(/[[:blank:]]/, "_", $h); printf "%s%s", $h, (h < NF ? OFS : ORS)}}' file
    
    'wiUEF7-gvouw_ow_wo24-RTeih_we', 'yt23IT_iug-76'
    

    【讨论】:

    • 这假定您的文本是以下模式:'text', 'text'。如果它偏离:'text', foo, 'text',那么使用FPAT 将删除文本的foo 部分。
    • 总会有一些假设。例如您假设输入是逗号分隔的,但 OP 没有在任何地方提到它。虽然可以使用-v FPAT="'[^']*'|[^,' ]+"
    【解决方案4】:

    在 perl 中:

    perl -i -pe's{(\x27.*?\x27)}{ (my $subst = $1) =~ tr/ /_/ }ge'  yourfile
    

    或使用perl5.14或更高版本:

    perl -i -pe's{(\x27.*?\x27)}{ $1 =~ tr/ /_/r }ge'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-12
      • 2020-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      相关资源
      最近更新 更多