Конфликт между GNU параллельно и awk (разбить столбец и отфильтровать несколько строк) - PullRequest
1 голос
/ 01 ноября 2019

Я работаю над многими большими файлами gz, как в приведенных ниже примерах (здесь показаны только первые 5 строк).

gene_id variant_id  tss_distance    ma_samples  ma_count    maf pval_nominal    slope   slope_se
ENSG00000223972.4   1_13417_C_CGAGA_b37 1548    50  50  0.0766871   0.735446    -0.0468165  0.138428
ENSG00000223972.4   1_17559_G_C_b37 5690    7   7   0.00964187  0.39765 -0.287573   0.339508
ENSG00000223972.4   1_54421_A_G_b37 42552   28  28  0.039548    0.680357    0.0741142   0.179725
ENSG00000223972.4   1_54490_G_A_b37 42621   112 120 0.176471    0.00824733  0.247533    0.093081

Ниже вывод, который я хочу.

Здесь я разделил второй столбец на «_» и выбрал строки на основе второго и третьего столбцов (после разделения) ($ 2 == 1 и $ 3> 20000). И я сохраняю это как текст. Команда ниже работает отлично.

zcat InputData.txt.gz | awk -F "_"  '$1=$1' | awk '{if ($2==1 && $3>20000) {print}}'  > OutputData.txt

ENSG00000223972.4   1 54421 A G b37 42552   28  28  0.039548    0.680357    0.0741142   0.179725
ENSG00000223972.4   1 54490 G A b37 42621   112 120 0.176471    0.00824733  0.247533    0.093081

Но я хочу использовать параллельный GNU для ускорения процесса, так как у меня есть много больших файлов gz для работы. Тем не менее, кажется, что есть некоторый конфликт между GNU параллельно и awk, вероятно, с точки зрения цитаты?

Я попытался определить опцию awk отдельно, как показано ниже, но она ничего не дала в выходном файле.

В приведенной ниже команде я запускаю параллель только для одного входного файла. Но я хочу запустить несколько входных файлов и сохранить несколько выходных файлов, каждый из которых соответствует одному входному файлу.

Например,

InputData_1.txt.gz для OutputData_1.txt

InputData_2.txt.gz для OutputData_2.txt

awk1='{ -F "_"  "$1=$1" }'
awk2='{if ($2==1 && $3>20000) {print}}' 
parallel "zcat {} | awk '$awk1' |awk '$awk2' > OutputData.txt" ::: InputData.txt.gz

Кто-нибудьесть предложения по этой задаче? Большое спасибо.


По предложению @karakfa это одно из решений

chr=1
RegionStart=10000
RegionEnd=50000
zcat InputData.txt.gz | awk -v chr=$chr -v start=$RegionStart -v end=$RegionEnd '{split($2,NewDF,"_")} NewDF[1]==chr && NewDF[2]>start && NewDF[2]<end {gsub("_"," ",$2) ; print > ("OutputData.txt")}' 

#This also works using parallel

awkbody='{split($2,NewDF,"_")} NewDF[1]==chr && NewDF[2]>start && NewDF[2]<end {gsub("_"," ",$2) ; print > ("{}_OutputData.txt")}'
parallel "zcat {} | awk -v chr=$chr -v start=$RegionStart -v end=$RegionEnd '$awkbody' " ::: InputData_*.txt.gz

Имя выходного файла для входного файла InputData_1.txt.gz будет InputData_1.txt.gz_OutputData.txt

Ответы [ 3 ]

2 голосов
/ 01 ноября 2019

https://www.gnu.org/software/parallel/man.html#QUOTING заключает:

Заключение: Чтобы избежать проблем с цитированием, может быть проще написать небольшой скрипт или функцию (помнитеэкспортировать -f функцию) и иметь параллельный вызов GNU.

Итак:

doit() {
  zcat "$1" |
    awk -F "_"  '$1=$1' |
    awk '{if ($2==1 && $3>20000) {print}}'
}
export -f doit
parallel 'doit {} > {=s/In/Out/; s/.gz//=}' ::: InputData*.txt.gz

1 голос
/ 01 ноября 2019

один из способов сделать это с помощью split

$ awk '{split($2,f2,"_")} 
   f2[1]==1 && f2[2]>20000 {gsub("_"," ",$2); print > (FILENAME".output")}' file

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

0 голосов
/ 01 ноября 2019

Простое решение состоит в том, чтобы объединить фильтр в один awk сценарий, тогда и только тогда, когда может работать параллель.

Вот пример решения, которое сканирует все input.txt только один раз (в два раза быстрее):

awk 'BEGIN{FS="[ ]*[_]?"}$2==1 && $7 > 20000 {print}' input.txt

Объяснение:

BEGIN{FS="[ ]*[_]?"} Сделать разделитель полей кратным "" или"_"

$2==1 && $7 > 20000 {print} Только для печатистроки со 2-м полем == 1 и 7-ное поле> 2000

Пример сценария отладки:

BEGIN{FS="[ ]*[_]?"}
{
    for(i = 1; i <= NF; i++) printf("$%d=%s%s",i, $i, OFS);
    print "";
}
$2==1 && $7 > 20000 {print}

Производим:

$1=gene $2=id $3=variant $4=id $5=tss $6=distance $7=ma $8=samples $9=ma $10=count $11=maf $12=pval $13=nominal $14=slope $15=slope $16=se 
$1=ENSG00000223972.4 $2=1 $3=13417 $4=C $5=CGAGA $6=b37 $7=1548 $8=50 $9=50 $10=0.0766871 $11=0.735446 $12=-0.0468165 $13=0.138428 
$1=ENSG00000223972.4 $2=1 $3=17559 $4=G $5=C $6=b37 $7=5690 $8=7 $9=7 $10=0.00964187 $11=0.39765 $12=-0.287573 $13=0.339508 
$1=ENSG00000223972.4 $2=1 $3=54421 $4=A $5=G $6=b37 $7=42552 $8=28 $9=28 $10=0.039548 $11=0.680357 $12=0.0741142 $13=0.179725 
ENSG00000223972.4   1_54421_A_G_b37 42552   28  28  0.039548    0.680357    0.0741142   0.179725
$1=ENSG00000223972.4 $2=1 $3=54490 $4=G $5=A $6=b37 $7=42621 $8=112 $9=120 $10=0.176471 $11=0.00824733 $12=0.247533 $13=0.093081 
ENSG00000223972.4   1_54490_G_A_b37 42621   112 120 0.176471    0.00824733  0.247533    0.093081
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...