Строковое переупорядочение слов с помощью awk - PullRequest
0 голосов
/ 09 мая 2018

Предположим, многострочный текстовый файл с двумя чередующимися типами строк. Первая строка начинается с «>» и содержит буквенно-цифровые строки, разделенные подчеркиванием. Вторая строка состоит из одной буквенно-цифровой строки.

$ cat file
>foo_bar_baz1
abcdefghijklmnopqrstuvwxyz0123456789
>foo_bar_baz2
abcdefghijklmnopqrstuvwxyz0123456789
>foo_bar_baz3
abcdefghijklmnopqrstuvwxyz0123456789

Я бы хотел изменить порядок слов в этих строках, начиная с ">".

$ cat file | sought_command
>baz1_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz2_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz3_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789

Я понимаю, что эту задачу можно выполнить с помощью awk .

Как мне нужно изменить приведенный ниже черновик awk код для достижения моей цели? В текущем виде приведенный ниже код печатает только строки, начинающиеся с «>», но не строки без них.

awk -F'_' '$1 ~ /^>/ { print ">"$3"_"$1"_"$2}' file | sed 's/>foo/foo/'
>baz1_foo_bar
>baz2_foo_bar
>baz3_foo_bar

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

После awk может помочь вам N полей для обработки в > строках в файле Input_file.

awk '/^>/{sub(/>/,"");num=split($0,a,"_");for(i=num;i>=1;i--){val=val?val OFS a[i]:a[i]};print ">"val;val="";next} 1' OFS="_"  Input_file

Теперь добавляем не-лайнерную форму решения.

awk '
/^>/{
  sub(/>/,"");
  num=split($0,a,"_");
  for(i=num;i>=1;i--){  val=val?val OFS a[i]:a[i]  };
  print ">"val;
  val="";
  next}
1
' OFS="_"   Input_file
0 голосов
/ 09 мая 2018

Вы также можете использовать sed один

$ sed -E 's/^>(.*)_([^_]+)$/>\2_\1/' ip.txt
>baz1_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz2_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz3_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
  • -E для включения расширенных регулярных выражений (в некоторых версиях может потребоваться опция -r)
    • используйте sed 's/>\(.*\)_\([^_]*\)$/>\2_\1/' ip.txt, если ERE не поддерживается
  • ^>(.*)_([^_]+)$ здесь ^ и $ - якоря начала и конца строки. _([^_]+)$ позволяет захватить последнюю строку после _, а (.*) будет иметь остаток строки
  • >\2_\1 при необходимости измените порядок
  • для редактирования на месте, см. флаг sed-in-place, который работает как на Mac (BSD), так и на Linux
0 голосов
/ 09 мая 2018

Вот один из способов. 1 напечатает все строки, в то время как будут изменены только нужные строки:

$ awk -F'_' '$1 ~ /^>/ {$0 = ">"$3"_"$1"_"$2}1' file | sed 's/>foo/foo/'
>baz1_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz2_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz3_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789

Вы можете предпочесть использовать substr вместо конвейера для sed:

$ awk -F'_' '$1 ~ /^>/ { $0 = ">" $3 "_" substr($1,2) "_" $2}1' file
>baz1_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz2_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
>baz3_foo_bar
abcdefghijklmnopqrstuvwxyz0123456789
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...