sed:为什么" s / TR [0-9] * // 2g"工作但不是" s / TR [0-9]。* // 2g"?

时间:2016-01-18 13:40:40

标签: regex sed

我的文件看起来像这样:

>TR45672|c1_g1_i1|m.87632TR21000
sometextherethatmayincludeTRbutnonumbers
>TR10000|c0_g1_i1|m.83558TR1702000
sometextherethatmayincludeTRbutnonumbers
....
....

我希望它看起来像这样:

>TR45672|c1_g1_i1|m.87632
sometextherethatmayincludeTRbutnonumbers
>TR10000|c0_g1_i1|m.83558
sometextherethatmayincludeTRbutnonumbers
....
....

换句话说,我想删除标题中第二次出现的模式TR(以">"开头的行)以及之后的所有内容,但不要触及行中的任何TR模式不是标题。在非标题行中,TR永远不会跟一个数字。

我尝试使用以下代码:

sed "s/TR[0-9].*//2g"

正如我所理解的那样,它将匹配TR然后匹配一个数字并删除除第一个之外的所有实例。由于标题中总是出现两次TR [0-9]而非标题中没有出现TR [0-9],这将实现我的目标......

......左右我想。实际上,使用上面的代码没有任何效果。

如果我改为跳过点并使用:

sed "s/TR[0-9]*//2g"

它为我手动检查的那些线产生了所需的结果。

问题:

(1)如果没有圆点但没有使用它怎么工作?我的理解是"。*"是模式之后删除所有内容的关键。

(2)删除点似乎有效,但我无法手动检查整个文件。在这种情况下,是否有理由怀疑在跳过点时会发生意外情况?

2 个答案:

答案 0 :(得分:4)

sed "s/TR[0-9].*//2g"

...匹配从第一行TR到行尾的整行,这意味着没有后续匹配(由于匹配全部已匹配,因此没有任何内容可供匹配)

sed "s/TR[0-9]*//2g"

...首先只匹配第一个TR<number>序列,然后在该行的其余部分找到第二个匹配。

答案 1 :(得分:3)

  1. 使用点分析输入文件的第一行与正则表达式:

    |--------------------------------  (1) TR matches 'TR' literally
    |  |------------------------------ (2) [0-9] match a single digit
    |  | |---------------------------- (3) .* matches any char till the end
    |  | |
    TR 4 5672|c1_g1_i1|m.87632TR21000
    11 2 3333333333333333333333333333
    ---------------------------------
    1st and only match  so there no 2nd match or above to replace
    
  2. 因此,使用TR[0-9].*,每行以TR开头,匹配。

    1. 如果您使用第二个正则表达式:

      |---------------------------------- (m1) TR matches 'TR' literally
      |  |------------------------------- (m1) [0-9]* match zero or more digits
      |  | 
      |  |                        |------ (m2) TR matches 'TR' literally
      |  |                        |  |--- (m2) [0-9]* match zero or more  
      TR 45672  |c1_g1_i1|m.87632 TR 21000
      --------                    --------
      1st match                   2nd match
      
    2. 顺便说一下,由于只有两个TR部分,您可以跳过global标记并使用:

      sed 's/TR[0-9]*//2' file