【问题标题】:Regex for replacing space with comma-space, except at end of line用逗号替换空格的正则表达式,行尾除外
【发布时间】:2017-03-15 09:31:48
【问题描述】:

我正在尝试隐藏这个的输入文件内容:

NP_418770.2: 257-296 344-415 503-543 556-592 642-707
YP_026226.4: 741-779 811-890 896-979 1043-1077

到这里:

NP_418770.2: 257-296, 344-415, 503-543, 556-592, 642-707
YP_026226.4: 741-779, 811-890, 896-979, 1043-1077

即用逗号和空格替换空格(不包括换行符)

为此,我已经尝试过:

perl -pi.bak -e "s/[^\S\n]+/, /g" input.txt

但它给出了:

NP_418770.2:, 257-296, 344-415, 503-543, 556-592, 642-707
YP_026226.4:, 741-779, 811-890, 896-979, 1043-1077

如何在不编写另一个正则表达式的情况下停止出现在“:”之后的附加逗号(我想要“:”和一个空格)?

谢谢

【问题讨论】:

  • /42/ 怎么样?
  • (对于那些感到困惑的人,最初的问题标题是“什么是完美的正则表达式?”抱歉@simbabque 破坏了你的笑话)。
  • 不是直接的答案,但对于这个用例,s/(\d) (\d)/$1, $2/g 怎么样?
  • 您是否有任何其他类型的空间,如制表符或在某些条件下需要替换的单个空格?这样您就可以只使用文字空格字符而不必担心\S \h \n 等...
  • 我最喜欢替换除某些模式之外的所有模式是使用SKIP....尽管在这种情况下使用s/^[^:]+:\h+(*SKIP)(*F)|\h+/, /g 似乎没有必要使用简单的替代方法

标签: regex perl


【解决方案1】:

你很亲密。这应该可以解决问题:

s/(\d+-\d+)[^\S\n]+/$1, /g

问题是,我尝试查看后面会出现逗号的部分,这些部分适用于“数字,然后是破折号,更多数字,然后是不是换行符的空格”的模式。有趣的是,我说“不是换行符的空白”部分是[^\S\n]+,意思是“不是非空白或换行符”(因为\S 不是\s,我们想要也排除换行符)。如果在任何情况下您有一些尾随空格,您可以在上面的正则表达式之前使用s/\s+$// 修剪它,只是不要忘记在此之后添加换行符。

【讨论】:

  • 可以简写为's/\d\K /, /g'
【解决方案2】:

尝试使用 regex 否定lookbehind。基本上看,如果空格前的字符是冒号(:),那么它与那个空格不匹配。

s/(?<!:)[^\S\n]+/, /g

【讨论】:

  • s/(?&lt;!:)\h+/, /g
  • \h+ 在这里做什么? @WiktorStribiżew
  • @xtreak: [^\S\n] 是匹配除换行符以外的任何空格的模式。我想 OP 需要匹配任何 horizo​​ntal 空格,所以我建议\h.
  • 请注意,这个正则表达式包含一个否定的lookbehind。并非所有引擎都支持它,例如默认的 Javascript 正则表达式引擎。
【解决方案3】:

您可以使用单词边界来丢弃冒号后面的空格:s/\b\h+/, /g

可以用perl完成:

perl -pe's/\b\h+/, /g' file

但也可以使用 sed:

sed -E 's/\b[ \t]+/, /g' file

使用字段分隔符的其他方法:

perl -F'\b\h+' -ape'BEGIN{$,=", "}' file

或者用 awk 做同样的事情:

awk -F'\b[ \t]+' -vOFS=', ' '1' file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多