【问题标题】:Replace all occurences of X with Y before match "xyz" using sed使用 sed 在匹配“xyz”之前将所有出现的 X 替换为 Y
【发布时间】:2020-07-23 01:02:42
【问题描述】:

我在一个文件中有一个 uri 列表:

https://<pattern>.hostname.com/api/<pattern>

有时模式包含一个在路径部分有效但在主机名中无效的下划线。我希望将主机名部分中的下划线转换为连字符,但将路径部分单独保留。所以想要的是:replace '_' with '-' before "/api" 有效。

https://ab_c.hostname.com/api/ab_c 应该变成https://ab-c.hostname.com/api/ab_c

如何使用sed 执行此操作?此处回答了在匹配单个字符之前替换字符 Replace all Occurences of '.' with '_' before '=' using sed ,但我无法调整它以通过多个字符匹配来达到想要的效果。

【问题讨论】:

  • 使用 GNU sed 的单行代码:sed -E ':a; s|^([^/]*//[^/]*)_([^/]*)|\1-\2|; ta' file

标签: regex awk sed


【解决方案1】:

实际上就像我在上一个帖子中提到的那样,awk 在我看来是最优雅的:

awk -F"/api" '{gsub(/\_/,"-",$1)}1' OFS=/api filename

成功了。

无论如何感谢您的解决方案!

【讨论】:

    【解决方案2】:

    在 bash 中可以这样做

    $ url=https://ab_c.de_fhostname.com/api/ab_c
    $ first=${url%/api/*}
    $ last=${url#*/api/}
    $ echo ${first//_/-}/api/$last
    https://ab-c.de-f.hostname.com/api/ab_c
    

    【讨论】:

      【解决方案3】:

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

      sed '\#/api#{s//\n&/;h;y/_/-/;G;s/\n.*\n//}' file
      

      分而治之或:

      sed ':a;s#_\(.*/api.*\)#-\1#;ta' file
      

      循环直到没有:

      【讨论】:

        【解决方案4】:

        Perl 来救援!

        perl -pe '($before) = m{(.*?/api)};
                  $before =~ s/_/-/g;
                  substr $_, 0, length $before, $before;
        ' -- file
        
        • 首先,我们将直到第一个/api 的部分提取到变量$before。
        • 我们将 $before 中的所有下划线替换为破折号。
        • 最后一步取整行并用新行替换初始部分。由于下划线与破折号的长度相同,因此我们知道我们需要删除完全相同数量的字符。

        【讨论】:

          【解决方案5】:

          另一个perl

          $ echo 'https://a_b_c_d.hostname.com/api/ab_c' | perl -pe 's|_(?=.*/api/)|-|g'
          https://a-b-c-d.hostname.com/api/ab_c
          

          _(?=.*/api/) 使用正向前瞻,因此 _ 仅在 /api/ 出现在该行的后面时才匹配。由于环视不消耗字符,因此不需要显式循环。


          sed类似的逻辑

          $ echo 'https://a_b_c_d.hostname.com/api/ab_c' | sed -E ':a s|_(.*/api/)|-\1|; ta'
          https://a-b-c-d.hostname.com/api/ab_c
          

          s|_(.*/api/)|-\1| 将替换 _- 仅当 /api/ 出现在该行的后面时。循环确保替换所有匹配项。

          【讨论】:

            猜你喜欢
            • 2015-01-08
            • 2011-10-21
            • 1970-01-01
            • 2016-07-24
            • 1970-01-01
            • 2021-09-30
            • 2023-02-02
            • 1970-01-01
            • 2019-08-25
            相关资源
            最近更新 更多