chr:pos1:pos2 Sun NC S1 S2 S3 S4 S9 S11 S14 S15 S16 S17 S18 S19 S28 S29 S30 S33 S34 S35 S36 S37 S38 S39
Aradu.A01:100145549:100145556 AG AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA
Aradu.A01:100408119:100408137 CA TA 0 0 0 TA TA TA TA TA TA TA TA TA TA TA TA TA TA TA TA 0
Aradu.A01:10102206:10102212 TG TA TA TA TA 0 TG TA TA TA TG TG TG TG TG TA TG TG TA 0 TG TG
Aradu.A01:10112010:10112029 GA GG GG GG GG GG GA GG GG GG GA 0 GA GA GA GG GA GA GG GA 0 GA
Aradu.A01:10112029:10112059 AC GC GC GC GC GC AC GC GC GC AC 0 AC AC AC GC AC 0 GC AC 0 AC
Aradu.A01:101198026:101198058 GT GC GC GC GT GC 0 GT GT GC GT GT GT 0 GT GC GT GC GC GT 0 GT
Aradu.A01:101198058:101198081 TC CC CC CC TC CC 0 TC TC CC TC TC TC 0 TC CC TC CC CC TC 0 TC
Aradu.A01:101306922:101306946 AG AA AA AA AG 0 AA AG AG AA 0 AG AG AG AG AA AG AG AA AG AG AG
В данном файле я пытаюсь сопоставить значения во всех полях столбца 4 и далее со столбцами 2 и 3. Если значение поля (столбец 4 и далее) совпадает с полем столбца 2, пометьте его как S , если он соответствует столбцу 3, пометьте его как N, а если он равен 0, присвойте ему -1.
Я попробовал следующее:
NR>1 {for(i=4;i<=NF;i++)
{ if ( $i == $2 ) $i=S ;
if ( $i == $3 ) $i=N ;
if ( $i == 0 ) $i=-1 ;
} ## if ;
## for loop is done
print ;
}
В результате всем полям, кроме первых 3, присвоено значение -1.
Похоже, это работает:
NR > 1 {
for( i=4; i<NF; i++) {
if( $i == $2 ) {
$i = "S"
}
else if( $i == $3 ) {
$i = "N"
}
else if( $i == 0 ) {
$i = -1
}
}
print
}
Поместите это в файл с именем e. г. 363142.awk
и запустите:
$ awk -f 363142.awk /path/to/input
perl -F\\s+ -pale '
$. > 1 and /(?:\S+\s+){3}/g and
s{\G(\S+)(\s*)}
{
($1 eq $F[1] ? "S" : $1 eq $F[2] ? "N" : $1 eq "0" ? -1 : $1) . $2
}cge;
' your_genes_file
-F\\s+
зададут для FS
один или несколько пробелов => /\s+/
- p
установит неявное чтение файла в цикле, И печать будет автоматической. -a
разделяет каждую запись заново на основе разделителя поля, предоставленного параметром -F
, или одиночного пробела по умолчанию. Поля хранятся в массиве @F
. -l
установит ORS=RS=\n
-e
— код Perl
, применяемый к каждой записи. Мы пропускаем первую строку из обработки. Опция -p
позаботится о его печати. Затем мы размещаем маркер нашего движка регулярных выражений в начале 4-го поля, так как именно здесь должны начинаться все действия. Затем применяем команду s///
в режимах global
, cumulative
и eval
. /c
=> маркер регулярного выражения начнется с того места, где он был припаркован в последней команде m//g
, а НЕ с начала. /g
=> просматривает всю строку для ее преобразования, а /e
просматривает секцию замены s//repl/
как Perl
код, который нужно выполнить, и его результаты помещаются в секцию замены.
Это можно написать в POSIX sed
, но тогда код будет мешать ясности, и его оставят в качестве умеренного упражнения.
sed -e '
1b
# fence the column 2 and go looking for col2 matching fields from col 4 onwards
s/\S\+/\n&\n/2
:c2
s/\(\n\(.*\)\n\s\+\S\+\s.*\)\<\2\>/\1S/g;tc2
s/\n//g
# fence the column 3 and go looking for col3 matching fields from col 4 onwards
s/\S\+/\n&\n/3
:c3
s/\(\n\(.*\)\n.*\)\<\2\>/\1N/g;tc3
s/\n//
# from col 4 onwards look for any lone 0s and change them to -1
:zm1
s/\(\n.*\)\<0\>/\1-1/;tzm1
s/\n//
' gene_file.dat
Здесь мы удаляем все начальные пробелы, которые будут мешать индексации массива @F, а затем восстанавливаем их во время печати данных. В map
мы передаем элементы с 6 и далее (4+2 для пробелов) и просто проверяем, равны ли они 2-му/3-му столбцам или 0.
perl -F'(\s+)' -lane '
print,next if $. == 1;
my $dummy = splice @F, 0, 2 if /^\h/;
print $dummy, @F[0..5], map {
s/^\Q$F[2]\E$/S/ or s/^\Q$F[4]\E$/N/ or s/^0$/-1/; $_
} @F[6 .. $#F];
' gene_file.dat