【问题标题】:sed find and replace for only specific number of occurrencessed 仅查找和替换特定数量的出现
【发布时间】:2017-07-15 13:36:39
【问题描述】:

我有以下问题。

我有一个带有序列的文件,我想找到一个特定的模式并将其替换为另一个模式,但仅限于特定的次数。

例如:

ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN

我想查找“DEFGHI”并将其替换为“ABCDEF”仅 3 次。

sed -i 's/DEFGHI/ABCDEF/g' /home/user/test.txt

我不想全局替换;相反,我只想更换 3 次。

【问题讨论】:

  • 对不起。我想用另一个模式替换。例如:带 ABCDEF 的 DEFGHI
  • 这很重要。模式可以每行出现一次以上吗?
  • @toolic 你假设每一行都有一个匹配项(即,如果它或多或少会中断)。
  • 我投票决定将此问题作为题外话结束,因为任务描述不清楚,并且 OP 没有回应澄清请求。 (特别是:模式是否可以在一行中出现多次?模式是否可以在一行中出现少于一次(即是否存在根本不匹配的行)?)
  • perl -pi -e's/DEFGHI/ABCDEF/ and $i++ if $i<3' /home/user/test.txt。用 sed 做起来非常困难。

标签: linux perl sed


【解决方案1】:

您可以将找到的第一个匹配项替换 3 次:

sed -i '0,/DEFGHI/s//ABCDEF/;0,/DEFGHI/s//ABCDEF/;0,/DEFGHI/s//ABCDEF/' file

输出:

ABCABCDEFJKLMN
ABCABCDEFJKLMN
ABCABCDEFJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN

【讨论】:

    【解决方案2】:

    这将替换给定模式三次,无论它们以哪种方式分布在行上

    perl -0777 -pe'$i += s/DEF/xxx/ while $i < 3' < data.txt  > out.txt
    

    它假设模式没有被分割线。它遍历字符串,每次都从头开始搜索。这带有一个警告,如下所述,虽然效率低,但很简单。

    如果替换本身在与周围的文本组合时重新创建了模式,那么这也将在下一次传递中被替换。这样的替换必须以特定的方式包含模式本身的部分内容。不过,如果这是一个问题,请告诉我。

    问题中未指定处理可能的重叠模式。如果有任何此解决方案将替换第一个解决方案,因此在下一次通过时,重叠的解决方案将消失。

    【讨论】:

    • @sidyll 的(已删除)答案有正确的想法并且很有帮助,谢谢
    【解决方案3】:

    这可以使用 bash 和 GNU sed 来完成,如下所示:

    sed -z -i "$(echo s/DEFGHI/ABCDEF/{3..1}\;)" yourfile
    
    • {3..1} 导致s 部分重复三次,标志为 3 到 1。每个 s 命令仅替换第三次、第二次和第一次出现。倒序是必须的,这样计数和替换就不会混淆。
    • -z 一次获取所有输入行,因此计数不是每行而是每个文件。

    供您参考,以下是 echo 周围的命令替换产生的内容:

    echo s/DEFGHI/ABCDEF/{3..1}\;
    > s/DEFGHI/ABCDEF/3; s/DEFGHI/ABCDEF/2; s/DEFGHI/ABCDEF/1;
    

    【讨论】:

    • @SLePort 你是对的。我颠倒了顺序。谢谢。
    • +1 表示 sed+shell 组合,它适用于除 3 以外的任意值。不过,要明确的是,这个“大括号扩展”... bash?所以它是 GNU sed+bash 和类似 bash 的 shell。
    猜你喜欢
    • 1970-01-01
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 2020-02-03
    相关资源
    最近更新 更多