【问题标题】:How to insert characters in the middle of every two consecutive repeating characters?如何在每两个连续重复字符的中间插入字符?
【发布时间】:2019-07-24 22:42:47
【问题描述】:

我有一个这样的文件:

user$ cat -t file
0.1^I^I^I0.2

我希望编辑文件,以便每次出现两个连续的选项卡时,在两个选项卡的中间插入字符“NA”。可以出现的连续制表符的数量是任意的(在此示例中,连续三个制表符,但可以是两个或三个以上)。

我试过用 sed (BSD sed) 来做这个:

user$ cat -t <(sed $'s/\t\t/\tNA\t/g' file)

但这只会在前两个连续制表符的中间插入所需的字符,从而产生以下输出:

0.1^INA^I^I0.2

我还需要将字符插入第二对连续制表符的中间以获得此输出:

0.1^INA^INA^I0.2

更愿意为此使用 sed,但也可以使用其他工具,例如 awk 或 perl。

【问题讨论】:

    标签: shell sed


    【解决方案1】:

    问题在于 sed 不进行 重叠 匹配。我们需要重复替换,直到完成所有匹配。因此,尝试:

    $ cat -t <(sed ':a; s/\t\t/\tNA\t/g; ta' file)
    0.1^INA^INA^I0.2
    

    考虑\t\t\t。替换命令匹配第一个\t\t 并将其替换为\tNA\t。问题是,使用g 选项,下一个替换只能在前两个制表符之后开始。不支持重叠替换。这就是为什么我们需要像上面那样添加标签和分支命令。

    工作原理

    • :a

      这会创建一个标签a

    • s/\t\t/\tNA\t/g

      这会做你想要的替换。

    • ta

      如果前面的替换命令成功地进行了替换,这会告诉 sed 跳回标签 a。因此,替换命令将根据需要重复多次。

    BSD 版本

    感谢mikekatz45,BSD版本为:

    cat -t <(sed -e :a -e $'s/\t\t/\tNA\t/g' -e ta file)
    

    请注意,虽然 $'...' 构造不是 POSIX,但它可以在 bashkshzsh 下工作。

    【讨论】:

    • 在 BSD sed 与 GNU sed 中使用 sed 标签时有什么注意事项?无法在 BSD sed 上复制它
    • @MikeKatz45 是的,通常存在 BSD 问题,不幸的是,我无法使用 BSD 机器进行尝试。不过,根据一般原则,请尝试:cat -t &lt;(sed -e :a -e 's/\t\t/\tNA\t/g' -e ta file)
    • 希望这将适用于 BSD 的版本,但无论如何,最好的答案是那些提醒解决问题的命令的较少使用方面的答案 - 而这个问题在那里击中了靶心。 .
    • cat -t &lt;(sed -e :a -e $'s/\t\t/\tNA\t/g' -e ta file)在BSD sed上工作
    • @MikeKatz45 干得好!我已更新答案以添加您的 BSD 版本。
    【解决方案2】:

    Perl 版本使用 0 宽度的前瞻来使匹配不重叠:

    $ echo -e "0.1\t\t\t0.2" | perl -pe 's/\t(?=\t)/\tNA/g' | cat -t
    0.1^INA^INA^I0.2
    

    或者就地修改文件:

    $ perl -pi -e 's/\t(?=\t)/\tNA/g' blah.txt
    

    【讨论】:

      猜你喜欢
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多