Как заменить строку в файле двумя колонками? - PullRequest
1 голос
/ 14 октября 2019

Содержимое моего файла выглядит следующим образом: (два столбца, разделенные «табуляцией»)

Others  ___
Archaea ___
Archaea_Euryarchaeota   ___
Archaea_Methanomicrobia_o_RCII  ___
Bacteria1       ___
Bacteria2       ___
Bacteria;p__Acidobacteria;c__Holophagae;o__Holophagales;f__Holophagaceae;g__    g__
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;__;__       ___
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;f__;g__     g__
Bacteria;p__Acidobacteria;c__Sva0725;o__Sva0725;f__;g__ g__
Bacteria;p__Acidobacteria;c__[Chloracidobacteria];o__;f__;g__   g__
Bacteria;p__Acidobacteria;c__iii1-8;o__SJA-36;f__;g__   g__
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__;g__        g__
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__EB1017;g__  g__
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__Microthrixaceae;g__ g__
Bacteria;p__Actinobacteria;c__Actinobacteria;__;__;__   ___

Я пытаюсь сделать это:

Когда я нахожу g__ во второмстолбец, то мне нужно заменить его последним найденным словом (после p__ или c__ или o__ или f__ или g__) в первом столбце. Например, в строке

Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__Microthrixaceae;g__ g__

g__ во втором столбце следует заменить на Microthrixaceae.

Аналогично, для случая, когда ___ найден, заменить на последнийнайденное слово (после p__ или c__ или o__ или f__ или g__) в первом столбце. Буду очень признателен за ваши предложения. Спасибо!

Вывод должен выглядеть так:

Others  ___
Archaea ___
Archaea_Euryarchaeota   ___
Archaea_Methanomicrobia_o_RCII  ___
Bacteria1       ___
Bacteria2       ___
Bacteria;p__Acidobacteria;c__Holophagae;o__Holophagales;f__Holophagaceae;g__ Holophagaceae    
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;__;__       Solibacterales
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;f__;g__     Solibacterales
Bacteria;p__Acidobacteria;c__Sva0725;o__Sva0725;f__;g__ Sva0725
Bacteria;p__Acidobacteria;c__[Chloracidobacteria];o__;f__;g__   Chloracidobacteria
Bacteria;p__Acidobacteria;c__iii1-8;o__SJA-36;f__;g__   SJA-36
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__;g__        Acidimicrobiales
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__EB1017;g__  EB1017
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__Microthrixaceae;g__ Microthrixaceae
Bacteria;p__Actinobacteria;c__Actinobacteria;__;__;__   Actinobacteria

Ответы [ 3 ]

1 голос
/ 14 октября 2019

awk или perl или даже sed - определенно лучший выбор, чем чистый bash. Вот решение perl:

perl -pe 's/(.*?)([a-z]__\[?)([A-Za-z0-9-]+)(\])?(;[a-z]?__)*(\t)([g_]__)/$1$2$3$4$5\t$3/' yourfilename

Чтобы пояснить, почему это работает, наведите курсор мыши на выделенную строку регулярного выражения здесь: https://regex101.com/r/tLpMCG/1

(Обратите внимание, что регулярное выражение оченьнемного отличается от этого ответа, потому что здесь я использовал perl, но там я был вынужден использовать php, и мне было трудно вставлять во вкладки.)

0 голосов
/ 14 октября 2019

Поскольку sed:

sed -E 's/^([^\t]*)((p|c|o|f)__[[]?([^];[:space:]]+))([^\t]*)\t(g|_)__/\1\2\5\t\4/'

Поскольку регулярные выражения являются жадными, это get становится последним словом после (p|c|o|f)__ и заменяет второй столбец.

Проверено с:

cat <<EOF | tr -s ' ' | tr ' ' '\t' |
Others  ___
Archaea ___
Archaea_Euryarchaeota   ___
Archaea_Methanomicrobia_o_RCII  ___
Bacteria1       ___
Bacteria2       ___
Bacteria;p__Acidobacteria;c__Holophagae;o__Holophagales;f__Holophagaceae;g__    g__
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;__;__       ___
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;f__;g__     g__
Bacteria;p__Acidobacteria;c__Sva0725;o__Sva0725;f__;g__ g__
Bacteria;p__Acidobacteria;c__[Chloracidobacteria];o__;f__;g__   g__
Bacteria;p__Acidobacteria;c__iii1-8;o__SJA-36;f__;g__   g__
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__;g__        g__
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__EB1017;g__  g__
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__Microthrixaceae;g__ g__
Bacteria;p__Actinobacteria;c__Actinobacteria;__;__;__   ___
EOF
sed -E 's/^([^\t]*)((p|c|o|f)__[[]?([^];[:space:]]+))([^\t]*)\t(g|_)__/\1\2\5\t\4/'

создает:

Others  ___
Archaea ___
Archaea_Euryarchaeota   ___
Archaea_Methanomicrobia_o_RCII  ___
Bacteria1   ___
Bacteria2   ___
Bacteria;p__Acidobacteria;c__Holophagae;o__Holophagales;f__Holophagaceae;g__    Holophagaceae
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;__;__   Solibacterales
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;f__;g__ Solibacterales
Bacteria;p__Acidobacteria;c__Sva0725;o__Sva0725;f__;g__ Sva0725
Bacteria;p__Acidobacteria;c__[Chloracidobacteria];o__;f__;g__   Chloracidobacteria
Bacteria;p__Acidobacteria;c__iii1-8;o__SJA-36;f__;g__   SJA-36
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__;g__    Acidimicrobiales
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__EB1017;g__  EB1017
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__Microthrixaceae;g__ Microthrixaceae
Bacteria;p__Actinobacteria;c__Actinobacteria;__;__;__   Actinobacteria

Краткое объяснение ^([^\t]*)((p|c|o|f)__[[]?([^];[:space:]]+))([^\t]*)\t(g|_)__ регулярное выражение:

  • ^ - совпадение начала файла
  • ([^\t]*) - сопоставьте и запомните все перед (p|c|o|f)__. Мы сопоставляем до \t, потому что нас интересует только первое поле
  • ((p|c|o|f)__[[]?([^];[:space:]]+))
    • (p|c|o|f)__ - соответствует начальный префикс
    • [[]? - опциональноудалите [ перед ним
    • ([^];[:space:]]+) - вы не определили, что это за слово - я соответствую, пока ; или ] или пробел не будет найден.
  • ([^\t]*) - сопоставить остаток первого поля
  • \t - разделитель
  • (g|_)__ - сопоставить второе поле
0 голосов
/ 14 октября 2019

Один в GNU awk:

$ awk -F"[\t;]" '
BEGIN {
    p="^[pcofg]_+"
}
{
    for(i=NF-1;i>=1;i--)
        if($i~p "[^_$]") {
            b=$i
            sub(p,"",b)
            print gensub(/[^;\t]+$/,b,1,$0)
            next
        }
}1' file

Выход:

Others  ___
Archaea ___
Archaea_Euryarchaeota   ___
Archaea_Methanomicrobia_o_RCII  ___
Bacteria1       ___
Bacteria2       ___
Bacteria;p__Acidobacteria;c__Holophagae;o__Holophagales;f__Holophagaceae;g__    Holophagaceae
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;__;__       Solibacterales
Bacteria;p__Acidobacteria;c__Solibacteres;o__Solibacterales;f__;g__     Solibacterales
Bacteria;p__Acidobacteria;c__Sva0725;o__Sva0725;f__;g__ Sva0725
Bacteria;p__Acidobacteria;c__[Chloracidobacteria];o__;f__;g__   [Chloracidobacteria]
Bacteria;p__Acidobacteria;c__iii1-8;o__SJA-36;f__;g__   SJA-36
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__;g__        Acidimicrobiales
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__EB1017;g__  EB1017
Bacteria;p__Actinobacteria;c__Acidimicrobiia;o__Acidimicrobiales;f__Microthrixaceae;g__ Microthrixaceae
Bacteria;p__Actinobacteria;c__Actinobacteria;__;__;__   Actinobacteria
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...