匹配模式和空格之后的任意字符,并使用 sed 重新排列捕获的模式

匹配模式和空格之后的任意字符,并使用 sed 重新排列捕获的模式

我想找到一个特定的模式(k__)以及它之后的任何字符(直到空格),然后将捕获的模式移动到行尾

使用此示例文件:

cat test.file
37099   k__Eukaryota species:s__Isochrysis galbana;genus:g__Isochrysis;family:f__Isochrysidaceae;order:o__Isochrysidales;class:c__Haptophyta;phylum:p__Haptista
73015   k__Eukaryota species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__
73015   k__Eukaryota species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__
73015   k__Eukaryota species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__
73015   k__Eukaryota species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__
73015   k__Eukaryota species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__
43925   k__Eukaryota species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__
43925   k__Eukaryota species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__
43925   k__Eukaryota species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__
43925   k__Bacteria species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__

因此,我想匹配k__Eukaryotak__Bacteria(以及以 开头的其他模式k__),然后将捕获的匹配项移动到行尾。所需输出:

37099    species:s__Isochrysis galbana;genus:g__Isochrysis;family:f__Isochrysidaceae;order:o__Isochrysidales;class:c__Haptophyta;phylum:p__Haptista k__Eukaryota
73015    species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__ k__Eukaryota
73015    species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__ k__Eukaryota
73015    species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__ k__Eukaryota
73015    species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__ k__Eukaryota
73015    species:s__Monodus sp. CCMP505;genus:g__Monodus;family:f__Pleurochloridaceae;order:o__Mischococcales;class:c__Xanthophyceae;phylum:p__ k__Eukaryota
43925    species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__ k__Eukaryota
43925    species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__ k__Eukaryota
43925    species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__ k__Eukaryota
43925    species:s__Nannochloropsis oculata;genus:g__Nannochloropsis;family:f__Monodopsidaceae;order:o__Eustigmatales;class:c__Eustigmatophyceae;phylum:p__ k__Bacteria

我以为这很容易,但我做不到。以下是我尝试过的方法:

cat test.file | gsed -E 's#(.*k__)(k__\w\+)(.*)#\1\3\2#'

捕获文本直到模式,然后匹配(捕获模式和任何单词字符直到空格)然后捕获到行尾,然后更改捕获组的顺序。

我认为我可以反向引用这些模式来更改顺序,但我可能没有正确匹配它们。如何捕获我的模式,模式 ( k__xyz),然后匹配到行尾,捕获这些组并重新组织?这是正确的方法吗?

答案1

主要s#(.*k__)(k__\w\+)(.*)#\1\3\2#问题是第一个捕获组需要k__,第二个捕获组需要需要。您的文件每行k__包含一个。k__

由于您希望k__与相邻文本一起移动到行尾,因此它应该属于第二组。在第一组中,有一个名为积极展望可用于确保k__之后正确。sed不支持该功能,但这里实际上不需要它。第二个捕获组紧跟在第一个捕获组之后,并且需要k__

修复命令的最简单方法是k__从第一组中删除:

<test.file gsed -E 's#(.*)(k__\w+)(.*)#\1\3 \2#'

注意我使用了+而不是 ,\+因为这sed在我的 Debian 中的 GNU 中有效。我还在\3和之间添加了一个空格\2(另一种选择是:s#(.*)( k__\w+)(.*)#\1\3\2#,因此您不会在前导数字后得到四个空格;但您想要的文本确实在那里指定了四个空格)。

一个潜在的问题是第一组是贪婪的。当一行中.*只有一个时,这是可以的;否则第二组可能会匹配一些稍后的。至少有两个解决方案:k__k__

  1. 简单的非贪婪匹配:一般来说.*?但不是sed
  2. 第一组中更具体的模式,在您的情况下该组可能是( *[0123456789]+ *)

附注:为什么<test.file不是cat test.file |?请参阅后半部分我的这个答案

相关内容