【问题标题】:find pattern and characters up to space, and move captured pattern to end of line sed查找模式和字符直到空格,并将捕获的模式移动到行尾 sed
【发布时间】:2021-12-01 12:49:37
【问题描述】:

我想找到一个特定的模式(“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__Eukaryota”和“k__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#'

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

我想我可以回溯参考这些模式来更改顺序,但我很可能。没有正确匹配它们。如何捕获我的模式,模式(“K__xyz”)然后匹配到行尾,捕获这些组并重新组织?这是正确的方法吗?

非常感谢任何帮助!

唱片

【问题讨论】:

  • sed -E 's/^([^k]{1,})([^ ]{1,})(.*)$/\1\3 \2/' test.file
  • 任何解决方案都有效吗?如果您仍然需要这方面的帮助,请告知。

标签: regex sed


【解决方案1】:

如果要编辑原始文件,请添加“-i”选项;
sed -i -r 's/(.*)(k__[^ ]*)( .*)/\1\3 \2/g' test.file
如果要将结果保存到其他文件,请删除 '-i' 选项;
sed -r 's/(.*)(k__[^ ]*)( .*)/\1\3 \2/g' test.file > new.file

我的测试结果:

szvp000006656:/home # 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

szvp000006656:/home # sed -r 's/(.*)(k__[^ ]*)( .*)/\1\3 \2/g' test.file > new.file
szvp000006656:/home # cat new.file
37099    species:s__Isochrysis galbana;genus:g__Isochrysis;family:f__Isochrysidaceae;order:o__Isochrysidales;class:c__Haptophyta;phylum:p__Haptista k__Eukaryota

szvp000006656:/home # sed -i -r 's/(.*)(k__[^ ]*)( .*)/\1\3 \2/g' test.file
szvp000006656:/home # cat test.file
37099    species:s__Isochrysis galbana;genus:g__Isochrysis;family:f__Isochrysidaceae;order:o__Isochrysidales;class:c__Haptophyta;phylum:p__Haptista k__Eukaryota

注意:

  1. 推荐使用https://regexr.com/调试正则语法
  2. 基本的和扩展的 Posix/GNU 正则表达式都不能识别非贪婪量词;你需要一个以后的正则表达式。试试这个非贪婪的正则表达式 [^/]* 而不是 .*? chaos-stackoverflow

【讨论】:

  • 您不需要第一个捕获组。 sed -E 's/(k__[^ ]+) (.*)/\2 \1/' 可以简单地编辑以匹配开头的部分。
【解决方案2】:

使用这个 Perl 单行代码:

perl -lpe 's{^(.*?\s)(k__\S+)\s+(.*)}{$1$3 $2}' test.file > out.file

Perl 单行代码使用这些命令行标志:
-e:告诉 Perl 查找内联代码,而不是在文件中。
-p:循环输入一行一次,默认分配给$_。在每次循环迭代后添加print $_
-l:在执行内联代码之前去除输入行分隔符(默认情况下 *NIX 上为"\n"),并在打印时附加它。

^:行首。
(.*?\s):0个或多个任意字符(非贪心),以空格结尾,捕获并存储在变量$1中。
(k__\S+) :文字 k__ 后跟 1 个或多个非空白字符,捕获并存储在变量 $2 中。
\s+(.*) :1 个或多个空白字符。然后 0 个或多个任意字符,捕获并存储在变量 $3 中。

另请参阅:
perldoc perlrun: how to execute the Perl interpreter: command line switches
perldoc perlre: Perl regular expressions (regexes)

【讨论】:

  • perl -pe 's/k__\S+//; $k=$&; s/$/ $k/' -- 让 perl 删除字符串,该字符串保存为$&,然后将其存储在$k,然后将行尾替换为$k ...利用perl 有但 sed 没有的变量(除了保持空间)。
  • 哦,或者这个:perl -lpe 's/k__\S+//; $_="$_ $&"' ... 无论如何,是的 perl。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多