Разделитель полей awk для разделения определенного столбца не работает должным образом, $0 возвращает неразделенную запись?

Я пытаюсь разделить запись с помощью подчеркивания. Изначально речь шла о _ и . в качестве FS и только для первого столбца. Но прямо сейчас кажется, что никакое разделение не работает вообще?

cat test_file.tsv

mg.reads.per.gene_bcsZ_A1.tsv   contig_21128    476
mg.reads.per.gene_bcsZ_A1.tsv   contig_3712     1774
mg.reads.per.gene_bcsZ_A2.tsv   contig_38480    184
mg.reads.per.gene_bcsZ_A2.tsv   contig_62779    1154
mg.reads.per.gene_bcsZ_A4.tsv   contig_115486   113
mg.reads.per.gene_bcsZ_A4.tsv   contig_14345    937
mg.reads.per.gene_bcsZ_A5.tsv   contig_19362    426
mg.reads.per.gene_bcsZ_A5.tsv   contig_53656    31
mg.reads.per.gene_bcsZ_A6.tsv   contig_100190   26
mg.reads.per.gene_bcsZ_A6.tsv   contig_23343    164

и я пробовал множество вариантов, таких как

awk 'BEGIN { FS = _ } ; {print $0}' test_file.tsv
awk 'BEGIN { FS = '_' } ; {print $0}' test_file.tsv
awk 'BEGIN { FS = "_" } ; {print $0}' test_file.tsv
awk 'BEGIN { FS ="_" } ; {print $0}' test_file.tsv
awk  -F'_' '{print $0}' test_file.tsv
awk -F"gene" '{print $0}' test_file.tsv

и это дает неизменный результат. Я ожидал:

mg.reads.per.gene   bcsZ    A1.tsv   contig 21128    476
mg.reads.per.gene   bcsZ    A1.tsv   contig 3712     1774
mg.reads.per.gene   bcsZ    A2.tsv   contig 38480    184
mg.reads.per.gene   bcsZ    A2.tsv   contig 62779    1154
mg.reads.per.gene   bcsZ    A4.tsv   contig 115486   113
mg.reads.per.gene   bcsZ    A4.tsv   contig 14345    937
mg.reads.per.gene   bcsZ    A5.tsv   contig 19362    426
mg.reads.per.gene   bcsZ    A5.tsv   contig 53656    31
mg.reads.per.gene   bcsZ    A6.tsv   contig 100190   26
mg.reads.per.gene   bcsZ    A6.tsv   contig 23343    164

Я пропустил что-то очевидное здесь?

РЕДАКТИРОВАТЬ: да, я сделал: «Распространенной ошибкой является попытка изменить разделители полей в записи, просто установив FS и OFS, а затем ожидая простой «печати» или «печати $0» для печати измененной записи. (руководство по awk, "понимание $0")

РЕДАКТИРОВАТЬ: и для достижения конечной цели (разделение на _ и . только в первом столбце, это работает (по крайней мере, в одной строке, разделенной ";")):

    awk 'BEGIN { OFS = "\t" }
  {
  split ($1, a, "_") 
  split (a[3], b, "\\.") 
  print $2, a[2], b[1]
  }' test_file.tsv

выход:

contig_21128    bcsZ    A1
contig_3712     bcsZ    A1
contig_38480    bcsZ    A2
contig_62779    bcsZ    A2
contig_115486   bcsZ    A4
contig_14345    bcsZ    A4
contig_19362    bcsZ    A5
contig_53656    bcsZ    A5
contig_100190   bcsZ    A6
contig_23343    bcsZ    A6

person crazysantaclaus    schedule 16.03.2018    source источник
comment
Что вы ожидаете от print $0 распечатать? Вот и вся линия. Если вам нужно первое значение, выполните print $1.   -  person Davy M    schedule 17.03.2018
comment
Я бы хотел, чтобы во всей строке не было больше _ и, следовательно, 6 столбцов вместо 3   -  person crazysantaclaus    schedule 17.03.2018
comment
Какой результат вы ожидаете?   -  person Benjamin W.    schedule 17.03.2018
comment
что бы я сделал, чтобы напечатать всю строку (с помощью awk), чтобы увидеть, сработало ли разделение? Итак, получите ожидаемый результат, упомянутый выше?   -  person crazysantaclaus    schedule 17.03.2018
comment
Я отредактировал вопрос, так как, видимо, хотел, чтобы awk сделал что-то не так.   -  person crazysantaclaus    schedule 17.03.2018


Ответы (2)


$0 — это вся строка в awk.

 awk -F_ '{$1=$1;print}' sample.csv

Разделитель полей ввода — _, а разделитель полей вывода по умолчанию — пробел. {$1=$1;print} перестраивает поля на основе выходного разделителя и печатает их все.

выход:

mg.reads.per.gene bcsZ A1.tsv   contig 21128    476
mg.reads.per.gene bcsZ A1.tsv   contig 3712     1774
mg.reads.per.gene bcsZ A2.tsv   contig 38480    184
mg.reads.per.gene bcsZ A2.tsv   contig 62779    1154
mg.reads.per.gene bcsZ A4.tsv   contig 115486   113
mg.reads.per.gene bcsZ A4.tsv   contig 14345    937
mg.reads.per.gene bcsZ A5.tsv   contig 19362    426
mg.reads.per.gene bcsZ A5.tsv   contig 53656    31
mg.reads.per.gene bcsZ A6.tsv   contig 100190   26
mg.reads.per.gene bcsZ A6.tsv   contig 23343    164
person Haifeng Zhang    schedule 16.03.2018
comment
так что $1 = $1 в принципе ничего не меняет, но заставляет awk перезагружаться? - person crazysantaclaus; 17.03.2018
comment
@crazysantaclaus, который он использует для восстановления записи, вы можете получить дополнительную информацию здесь: gnu.org/software/gawk/manual/html_node/Changing-Fields.html - person Haifeng Zhang; 17.03.2018

Вы неправильно понимаете использование разделителя полей в Awk. Разделитель полей Awk сообщает Awk, какое значение использовать для разделения столбцов во входных данных, где по умолчанию используется пробел.

Чтобы помочь вам понять, что происходит, вот что вы сейчас делаете (я сократил файл данных всего до 3 строк, чтобы им было легче управлять):

$awk -F "_" '{print $0}' test_file.tsv
mg.reads.per.gene_bcsZ_A1.tsv   contig_21128    476
mg.reads.per.gene_bcsZ_A1.tsv   contig_3712     1774
mg.reads.per.gene_bcsZ_A2.tsv   contig_38480    184
$awk -F "_" '{print $1}' test_file.tsv
mg.reads.per.gene
mg.reads.per.gene
mg.reads.per.gene
$awk -F "_" '{print $2}' test_file.tsv
bcsZ
bcsZ
bcsZ
$awk -F "_" '{print $3}' test_file.tsv
A1.tsv   contig
A1.tsv   contig
A2.tsv   contig
$awk -F "_" '{print $4}' test_file.tsv
21128    476
3712     1774
38480    184

Смотрите, вы разделили свой вывод ровно на 4 столбца, разбитых каждый раз, когда есть подчеркивание, которые в awk обозначаются как $1, $2, $3 и $4. Обратите внимание, что $0 возвращает все столбцы, объединенные разделителем полей, что выглядит так же, как ваш первоначальный ввод.

Что вы хотите, так это поменять местами все символы подчеркивания на пробелы, чтобы было 6 столбцов. Это можно сделать очень легко с помощью команды tr:

$ tr '_' ' ' < test_file.tsv 
mg.reads.per.gene bcsZ A1.tsv   contig 21128    476
mg.reads.per.gene bcsZ A1.tsv   contig 3712     1774
mg.reads.per.gene bcsZ A2.tsv   contig 38480    184

Теперь у вас есть шесть столбцов, и вы можете передать вывод в awk, если хотите, после этого для чего-то еще, что вы хотите сделать.

person Davy M    schedule 16.03.2018
comment
это отличное объяснение! Я только 1 час пытался сделать что-то, что не сработало ;-), но Хайфжан показывает мне, как получить ожидаемый результат в awk, поэтому я приму его ответ. Возможно нет возможности принять 2 ответа? - person crazysantaclaus; 17.03.2018
comment
Нет, нет никакого способа принять два ответа, но это совершенно нормально, что есть два ответа. Принятие ответа — это просто отметка, показывающая, какой ответ помог вам больше всего, поэтому имеет смысл принять другой ответ, поскольку он помог вам больше всего. - person Davy M; 19.03.2018