Использование команды tr в awk для замены косой черты вертикальной чертой

У меня есть большой файл, содержащий несколько строк, которые выглядят примерно так:

>m160505_c100980652550000001823221307061611/31156/269-572 

Мне нужно заменить все косые черты вертикальными чертами. Я думаю, что awk — отличный способ сделать это — он быстрый и простой. Однако я не уверен, как включить tr и | в команду. Пока у меня есть следующее, но мне нужна помощь, чтобы исправить это.

awk '/^>/{tr{/}{|}; next}{print}' < Old.fasta > New.fasta

Я не против написания сценария для этого, но я чувствую, что awk может быть более быстрым способом сделать это. Спасибо


person Rob    schedule 05.08.2016    source источник
comment
awk — это не оболочка, это инструмент, который оболочка вызывает для манипулирования текстом, точно так же, как оболочка может вызывать программу на языке C. Вы не должны ожидать, что сможете вызывать команды оболочки непосредственно из awk, точно так же, как вы не можете вызывать их непосредственно из программы C.   -  person Ed Morton    schedule 05.08.2016


Ответы (3)


awk не имеет ни команды/функции tr, ни простого способа добиться того же эффекта. Поскольку вы отметили это "perl", я предполагаю, что вы также открыты для perl oneliner:

perl -lpe '/^>/ and tr{/}{|}' < Old.fasta > New.fasta

делает то же самое, что и awk пытается сделать; замените все / на | в строках, начинающихся с >.

person hobbs    schedule 05.08.2016
comment
Я знаю, что сказал awk, но ты прав. Я открыт для perl-решений, и мне больше всего нравится это, очень хорошие опубликованные решения. Хоббс спасибо! - person Rob; 05.08.2016

$ awk '/^>/{gsub("/","|")}1' file
>m160505_c100980652550000001823221307061611|31156|269-572

Если вам ДЕЙСТВИТЕЛЬНО нужна функция tr() в awk, вам придется написать ее, например:

$ cat tr.awk
function tr(oldStr,oldList,newList,     newStr,i,o2n,chr) {
    for (i=1; i<=length(oldList); i++) {
        o2n[substr(oldList,i,1)] = substr(newList,i,1)
    }
    for (i=1; i<=length(oldStr); i++) {
        chr = substr(oldStr,i,1)
        newStr = newStr (chr in o2n ? o2n[chr] : chr)
    }
    return newStr
}
{ print $0, "->", tr($0,"xyz","123") }

$ echo 'axbyczd' | awk -f tr.awk
axbyczd -> a1b2c3d
person Ed Morton    schedule 05.08.2016

sed здесь, наверное, проще всего:

$ sed '/^>/ s/\//|/g' <<<'>m160505_c100980652550000001823221307061611/31156/269-572'
>m160505_c100980652550000001823221307061611|31156|269-572
  • После сопоставления > в начале строки (^) - с регулярным выражением, заключенным в (обязательные) разделители /.../,

  • s/\//|/g заменяет (s) | на каждое (g) / (экранировано как \/, потому что / используется в качестве разделителя регулярных выражений).

Использование альтернативного разделителя @ для ясности: sed s'/^>/ s@/@|@g'.


Вариант, который работает аналогично отдельной утилите tr, используя функцию y sed:

sed '/^>/ y/\//|/' <<<'>m160505_c100980652550000001823221307061611/31156/269-572'
  • Функция y заменяет любые символы в 1-м аргументе отдельно на соответствующий символ во 2-м аргументе — обратите внимание, что это означает, что 1-й и 2-й аргументы должны имеют одинаковую длину (tr этого не требует).
person mklement0    schedule 05.08.2016