ls -dlp *2010*
было бы хорошее начало к решению, но оно зависит, на что Вы хотите, чтобы вывод был похож.
Со справкой из этого ответа
awk 'FNR==NR && FNR>1 {a[$2] = $5; next}
FNR > 1 && ($2 in a) && $3 == "ALL" {
print $1 " " $2 " " a[$2] " " $9
}' file2 file1
Для получения заголовка также просто добавьте это к началу сценария:
BEGIN{print "CHR SNP MAF P"}
Объяснение:
В первую очередь, когда два файла передаются awk, они обрабатываются один за другим. Существует две переменные, важные здесь: NR
номер строки с начала awk
команда, и FNR
номер строки с начала текущего файла. Таким образом, когда первый файл обрабатывается (здесь file2), NR
и FNR
имейте то же значение, которое является значением строки, в настоящее время обрабатываемой. Но когда awk передают второму файлу, FNR
сбрасывается к 1, так, чтобы NR
и FNR
больше не то же. Так, чтобы тест FNR==NR
прием для знания, если обработанный файл является первым или нет.
Поэтому давайте см. код. Условие FNR==NR && FNR>1
тесты, обрабатываем ли мы первый файл а не первую строку. Если это имеет место, мы храним значение пятой колонны (MAF
) в массиве, индексированном вторым (SNP
) и затем next
в заявлении говорится для передачи следующей строке.
Когда awk обрабатывает второй файл (который является file1), первый тест является ложью, так, чтобы awk попробовал второй тест: FNR > 1 && ($2 in a) && $3 == "ALL"
, это: не первая строка файла + второе значение столбца (SNP
) существует в таблице a
+ третье значение столбца (TEST
) "ALL"
. Если это имеет место, то это печатает столбец 1 (CHR
) и два (SNP
), добирается MAF
значение от массива с a[$2]
, и затем столбец печати девять (P
).
Добавление a BEGIN{...}
оператор вначале добавляет команду, которая выполняется только, прежде чем первая строка обрабатывается.
terdon упоминает, что делал его с coreutils только, скромным предложением:
(echo CHR SNP MAF P
paste <(tail -n +2 file2) <(grep ALL file1) |
while read -r chr snp _ _ maf _ _ _ _ _ _ _ _ _ p; do
echo $chr $snp $maf $p;
done) | column -t
вывод:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
Вот один способ сделать его (скопировать/вставить это непосредственно в Ваш терминал):
(
awk -v OFS="\t" 'NR==1{print $1,$2,$5,"P"}' file2;
awk '$3=="ALL"{print $2,$NF}' file1 |
while read snp p; do
awk -v snp="$snp" -v p=$p -v OFS="\t" '$2==snp{print $1,$2,$5,p}' file2;
done
) > file3
Вывод похож на это:
CHR SNP MAF P
0 AFFX-SNP-000541 0 1
0 AFFX-SNP-002255 0 1
1 rs12103 C 0.5596
1 rs12103_1247494 C 0.5581
coreutils
, возможно, комбинация sort
,paste
и join
но я не мог понять это.-v OFS="\t"
если Вы не хотите это.awk
строка просто печатает 1-е, 2-е и 5-е поле заголовка файла 2, сопровождаемого P
. Это - заголовок нового файла.awk
печатает 2-е и последнее ($NF
) поля каждой строки file1, где 3-е поле ALL
.while
цикл, который читает эти два поля в переменные $snp
и $p
.awk
использование -v
опция и затем, для каждой строки file2, если второе поле $snp
, это печатает поля 1,2,5 и текущее значение $p
.Вот сценарий жемчуга, который делает то же:
perl -le 'print "CHR\tSNP\tMAF\tP"; open($f1, "$ARGV[0]");
while(<$f1>){
s/^\s+//; @f=split(/\s+/); $k{$f[1]}=$f[$#f] if $f[2] eq "ALL"
}
open($f2,"$ARGV[1]");
while(<$f2>){
s/^\s+//; @f=split(/\s+/);
next unless defined($k{$f[1]});
print "$f[0]\t$f[1]\t$f[4]\t$k{$f[1]}"
}' file1 file2
Вот еще один способ:
{ printf %s\\n "CHR SNP MAF P"; grep -F ALL file1 | sort -k2,2 | \
join -j2 -o 2.1,2.2,2.5,1.9 - <(sort -k2,2 file2); } | column -t
вывод:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
как это работает:
grep -F ВСЕ ФАЙЛ1 | сортирует -k2
печатает строки, соответствующие строке ALL
, затем сортирует
ed на 2-ом поле: Затем
0 AFFX-SNP-000541 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-002255 ALL 0 0 0/0/0 nan nan 1
1 rs12103_1247494 ALL C T 55/250/321 0.3994 0.4097 0.5581
1 rs12103 ALL C T 55/250/317 0.4019 0.4113 0.5596
соединяется во 2-ом поле (-j2
) со строкой file2 (также отсортированной во 2-ом поле) с помощью -o 2. 1,2.2,2.5,1.9
для вывода 1-го, 2-го и 5-го полей из файла2 и 9-го полей из обработанного файла1:
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
Так как это было сгруппировано {...}
с помощью printf %s\\n "CHR SNP MAF P"
, который печатает заголовок, то весь вывод затем претендует на столбец -t
.
Обратите внимание, что при таком решении порядок строк (из файла2) в выводе не сохраняется. Просто бывает, что ваш файл2 уже отсортирован по 2-му полю, но если бы это было не так, например:
CHR SNP A1 A2 MAF NCHROBS
0 AFFX-SNP-000541 0 0 NA 0
1 rs12103 C T 0.2894 1244
0 AFFX-SNP-002255 0 0 NA 0
1 rs12103_1247494 C T 0.2875 1252
и если бы вы хотели сохранить порядок строк, вы могли бы пронумеровать строки в file2 с помощью nl -ba -nrz file2
:
000001 CHR SNP A1 A2 MAF NCHROBS
000002 0 AFFX-SNP-000541 0 0 NA 0
000003 1 rs12103 C T 0.2894 1244
000004 0 AFFX-SNP-002255 0 0 NA 0
000005 1 rs12103_1247494 C T 0.2875 1252
перед сортировкой и присоединением и настроить команду: join on 2-е поле (обработанного) файла1 и 3-е поле (обработанного) файла2 и вывести поле номера строк + те же самые поля, что и первое решение join -1 2 -2 3 -o 2. 1,2.2,2.3,2.6,1. 9
затем повторно сортируйте вывод с помощью сортируйте -k1n
и удалите первое поле с помощью разрезайте -d'' -f2-
перед тем, как соединить весь вывод со столбцом -t
:
{ printf %s\\n "CHR SNP MAF P"; grep -F ALL file1 | sort -k2,2 | join \
-1 2 -2 3 -o 2.1,2.2,2.3,2.6,1.9 - <(sort -k3,3 <(nl -ba -nrz file2)) | \
sort -k1n | cut -d' ' -f2-; } | column -t
вывод:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
1 rs12103 0.2894 0.5596
0 AFFX-SNP-002255 NA 1
1 rs12103_1247494 0.2875 0.5581
Обратите внимание, что оба решения предполагают, что в каждой строке встречается только одно ALL
, а именно 3-е поле (отсюда и grep -F ALL
). Если это не так, то для фильтрации только соответствующих строк придется использовать регресс.
BEGIN{print "CHR SNP MAF P"}
вначале. – JPG 06.02.2014, 21:08