【问题标题】:how to regex replace before colon?如何在冒号之前进行正则表达式替换?
【发布时间】:2022-01-23 10:11:14
【问题描述】:

这是我的原始字符串:

NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1

我只想在 ':' 之前的所有空格中添加反斜杠

所以,这就是我最终想要的:

NetworkManager/system\ connections/Wired\ 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1

我需要在 bash 中执行此操作,因此,sed、awk、grep 对我来说都可以。

我尝试过关注 sed,但它们都不起作用

echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/ .*\(:.*$\)/\\ .*\1/g'
echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/\( \).*\(:.*$\)/\\ \1.*\2/g'
echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/ .*\(:.*$\)/\\ \1/g'
echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/\( \).*\(:.*$\)/\\ \1\2/g'

感谢您回答我的问题。 我对stackoverflow还是很陌生,我不知道如何控制评论中的格式。 所以,我只是编辑我原来的问题

我的真实故事是:

当我执行 grep 或使用 cscope 搜索关键字时,例如 /etc 文件夹下的“address1”。 结果是这样的:

./NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1

如果我使用 vim 打开光标下的文件,假设我的 vim 光标现在位于单词“NetworkManager”上, 那么vim会将其理解为

"./NetworkManager/system"

这就是为什么我想在空格前添加“\”,这样搜索结果会更 vim 友好:)

我确实尝试过更改 cscope 的源代码,但很难完全做到这一点。所以必须做一个帖子替换:(

【问题讨论】:

  • 如果您可以使用支持\K(重置匹配开始并丢弃所有先前匹配的字符)和\G(将位置设置在末尾的位置)的平台前一个匹配或在第一个匹配之前的字符串开头),您可以使用以下正则表达式执行替换:^[^:]*?\K |\G[^:]*?\K 。 (每个\K 后面都有一个空格。)Demo。将光标悬停在链接上正则表达式的每个元素上,以获得对其功能的解释。
  • 这听起来很像XY Question,您试图通过转义它们而不是引用您的字符串来解决输入中的空格问题,特别是考虑到您的echo缺少引号的问题。你对那些让你认为需要在空格前添加反斜杠的字符串做了什么?
  • @EdMorton 感谢您的提问。我的真实故事是:当我执行 grep 或使用 cscope 在 /etc 文件夹下搜索关键字“address1”时。结果将是: ./NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 如果我使用 vim 打开光标下的文件,假设我的 vim 光标现在位于单词“NetworkManager ",那么vim会把它理解为"./NetworkManager/system",所以我想在空格前加上"\",这样搜索结果会更vim友好:)
  • 作为一个几乎每天使用grepcscope 大约30 年的人,我从来没有遇到过这个问题。我一直使用vi 而不是vim,但我从未尝试从vi 内部打开文件。根据我们在这里看到的问题,似乎很多人使用 vim 来处理更适合 shell 的事情!

标签: regex awk sed


【解决方案1】:

这可以在awk 程序中简单地完成,使用您展示的示例,请尝试以下操作。

awk 'BEGIN{FS=OFS=":"} {gsub(/ /,"\\\\&",$1)} 1' Input_file

解释: 简单的解释是,为这个程序设置字段分隔符和输出字段分隔符为:。然后在主程序中使用awkgsub(全局替换)函数。仅在第一个字段中用 \ 替换空格(根据 OP 的注释,它应该在 : 之前完成)然后打印行。

【讨论】:

    【解决方案2】:

    如果您只想在字符串中存在: 时进行替换,您可以检查是否至少有 2 列,将(输出)字段分隔符设置为冒号。

    数据:

    cat file                                                                                                                                       michaelvandam@Michaels-MacBook-Pro
    NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1
    NetworkManager/system connections/Wired 1.nmconnection 14 address1=10.1.10.71/24,10.1.10.1%
    

    awk中的示例:

    awk 'BEGIN {FS=OFS=":"}{if(NF>1)gsub(" ","\\ ",$1)}1' file
    

    输出

    NetworkManager/system\ connections/Wired\ 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1
    NetworkManager/system connections/Wired 1.nmconnection 14 address1=10.1.10.71/24,10.1.10.1
    

    【讨论】:

      【解决方案3】:

      perl one liner 在 bash 中使用 \G\K(类似 @CarySwoveland's comment)的想法。

      perl -pe 's/\G[^ :]*\K /\\ /g' myfile
      

      See this demo at tio.runpattern demo at regex101

      【讨论】:

        【解决方案4】:

        这可能对你有用(GNU sed):

         sed -E ':a;s/^([^: ]*) /\1\n/;ta;s/\n/\\ /g' file
        

        : 之前的空格替换为换行符,然后将换行符替换为\ 's。

        使用保持空间的替代方法:

         sed -E 's/:/\n:/;h;s/ /\\ /g;G;s/\n.*\n//' file
        

        在第一个 : 处分行。

        修改前面部分,删除中间部分并附加纯正的后面部分。

        【讨论】:

        • 第一个在macos中不起作用,第二个起作用。
        • @huangyingw 你是说第一个 GNU sed 解决方案在 macos 中不起作用?
        • 正确,第一个在macos中不起作用
        【解决方案5】:

        使用sed

        $  sed 's/\([a-z]\) /\1\\ /g' input_file
        NetworkManager/system\ connections/Wired\ 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1
        

        【讨论】:

        • 我认为这适用于用例,但不能回答问题,因为它应该替换 : 之前的所有空格
        【解决方案6】:

        我的回答很丑,我认为RavinderSingh13's answer 是唯一的,但我已经花时间写我的并且它有效(它是一步一步写的,但它是一个单行命令):

        我受到HatLess answer的启发:

        首先使用cut 获取: 之前的文本(我将字符串放在一个文件中以便于阅读,但这适用于echo):

        cut -d':' -f1 infile
        

        然后用sed替换空格:

        cut -d':' -f1 infile | sed 's/\([a-z]\) /\1\\ /g'
        

        然后echo输出没有换行:

        echo -n "$(cut -d':' -f1 infile | sed -e 's/\([a-z]\) /\1\\ /g')"
        

        添加缺少的: 及其后面的内容:

        echo -n "$(cut -d':' -f1 infile | sed -e 's/\([a-z]\) /\1\\ /g')" | cat - <(echo -n :) | cat - <(cut -d':' -f2 infile)
        

        【讨论】:

        • cutsed 的好组合感谢分享欢呼?
        猜你喜欢
        • 1970-01-01
        • 2019-01-07
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        相关资源
        最近更新 更多