【问题标题】:How to replace mth to nth occurance of a string in bash using sed?如何使用 sed 在 bash 中替换第 m 次到第 n 次出现的字符串?
【发布时间】:2020-08-16 05:56:07
【问题描述】:

我一直在寻找一种简单的方法来屏蔽(即用 * 替换)使用 sed 在每一行中给定模式的第 1 到第 3 次出现。

输入文本的格式是;

$ cat input
1234 4321 2356 7890
3456 4567 8765 0981
2345 2167 9876 1234

所需的输出;

**** **** **** 7890
**** **** **** 0981
**** **** **** 1234

环顾四周后,我找到了替换指定模式的第 n 次出现的方法。在这里,您如何替换给定输入中每行的第二个块。

$ cat input | sed  's/[0-9]\{4\}/****/2'
1234 **** 2356 7890
3456 **** 8765 0981
2345 **** 9876 1234

我们还可以替换 所有出现的给定模式 第 n 个出现开始。以下是你的做法。

$ cat input | sed  's/[0-9]\{4\}/****/2g'
1234 **** **** ****
3456 **** **** ****
2345 **** **** ****

P.S 我会很感激简单而愚蠢的解决方案。不是 awksed 中的标签和循环的解决方案。

【问题讨论】:

    标签: sed text-processing


    【解决方案1】:

    使用您的简单输入示例:

    sed -r 's/([0-9]{4} ){3}/**** **** **** /' input
    

    https://unix.stackexchange.com/a/155810/57293 中给出了更复杂的解决方案。

    另一个简单的解决方案(当您知道该行中模式的 nr 时)是

    rev input | sed -r 's/[0-9]{4}/****/g2' | rev
    

    【讨论】:

      【解决方案2】:

      第一个解决方案:恕我直言,如果您问我简单的解决方案,那么我会选择 awk。如果您的 Input_file 仅包含 4 个字段,那么只需将值分配给 3 个字段即可。

      awk '{$1=$2=$3="****"} 1'  Input_file
      

      第二个解决方案: 使用sed(这可能是 OP 试图编写的方式)。使用sed 的功能使用临时缓冲区来存储匹配的正则表达式,然后在替换时将其替换为****

      sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\) \(.*\)/**** **** **** \4/'  Input_file
      

      第三种解决方案: 使用 rev 反向打印 Input_file 然后只捕获第一个(实际上是 Input_file 中的最后一个字段),然后打印 3 次 **** 和再次将其反向打印,现在将以实际形式打印它:)

      rev Input_file | sed 's/\([^ ]*\).*/\1 **** **** **** ****/' | rev
      

      第 4 种解决方案: 更通用的解决方案,人们可​​以将字段编号范围从哪个字段到哪个字段的人想要将值更改为 **** 然后尝试关注(fromto 是可以由人设置的变量,以根据字段编号更改值。

      awk -v from="1" -v to="3" '{for(i=from;i<=to;i++){$i="****"}} 1' Input_file
      

      【讨论】:

      • 感谢您的清晰回答! awk 真的很容易。但实际上我想弄清楚如何在 sed 中使用“查找和替换”。你能告诉我们为什么我们把那个“1”放在最后吗?我检查了没有那个我没有得到任何输出,为什么任何其他整数而不是“1”也可以工作?
      • @MridulGain, Hey Mridul, awk 研究条件方法,然后采取行动。如果条件为真,则动作将发生;因此,通过提及1,我将条件设为 TRUE 并且没有提及任何操作,因此默认情况下会打印当前行,顺便说一句,我在 4 个中添加了 sed 解决方案,2 个是 sed。如果您有任何其他疑问,请让我知道:)
      【解决方案3】:

      你问的“简单”和“愚蠢”。我会让你决定这是怎么回事;)。 GNU sed 确实支持从 sed /../[n]g 开始替换的模式,但不允许停止范围。您可以提及2g,从第 2 次出现开始替换,但不能将范围定义为第 1 次到第 3 次出现。

      sed -e 's/[0-9]\{4\}/****/; s/[0-9]\{4\}/****/; s/[0-9]\{4\}/****/' file
      

      但是放弃awk 以进行这样的琐碎替换不是一个好主意。它比你想象的更有用、更简单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-05
        • 1970-01-01
        • 2018-08-11
        • 2016-05-07
        • 2018-03-24
        • 2019-07-02
        • 1970-01-01
        • 2013-02-20
        相关资源
        最近更新 更多