Всякий раз, когда вы видите записи, разделенные пустыми строками («абзацы», если хотите), «режим абзаца» Perl часто является хорошим решением:
$ perl -00lpe 'if(/NAME#AAAA/){s/\bAGE\s/#$&/; s/$/\nAGE NIL/;}' file
NAME#AAAA
STD 1
SEC A
#AGE 5
AGE NIL
NAME#BBBB
STD 2
SEC B
AGE 6
NAME#CCCC
STD 3
SEC C
AGE 7
NAME#AAAA
STD 4
#AGE 9
AGE NIL
NAME#AAAA
STD 7
SEC A
#AGE 12
AGE NIL
-00
: это активирует режим абзаца Perl , где каждый «абзац» (группа непустых строк до пустого) рассматривается как «строка». -l
: удаляет завершающие символы новой строки из каждой входной записи (каждый абзац) и добавляет новую строку к каждому вызову print
.
-pe
: print каждая входная запись после обработки применяет к нему сценарий, заданный параметром -e
. Таким образом, эти флаги заставляют perl
читать входной файл, применять сценарий к каждой записи и затем печатать результат. Сам сценарий выполняет:
if (/ NAME # AAAA /)
: если эта запись соответствует NAME # AAAA
. s / \ bAGE \ s / # $ & /
: s / foo / bar /
- это оператор подстановки. Он заменит foo
на bar
. Здесь я заменяю AGE
самим собой, которому предшествует #
. \ b
соответствует границам слов и исключает такие вещи, как ADAGE
из соответствия. $ &
- это специальная переменная, означающая «все, что было найдено. Итак, s / \ bAGE \ s / # $ & /
заменит AGE
на #AGE
. s / $ / \ nAGE NIL /
: $
соответствует концу записи. Таким образом, замена его на что-то другое будет добавляться в конец Эта команда добавляет AGE NIL
в конец сопоставленной записи.Обратите внимание, что все операции здесь чувствительны к регистру. Если вам нужно сопоставление без учета регистра, используйте вместо него следующее:
perl -00lpe 'if(/NAME#AAAA/i){s/\bAGE\s/#$&/i; s/$/\nAGE NIL/i;}' file
perl -lane '
@ARGV and $h{$F[0]}=$F[1],next;
print join $", map { $_, $h{$_} // "NA" } @F;
' File2 File1
GeneA Ensembl1 GeneB Ensembl2
GeneA Ensembl1 GeneD NA
GeneC Ensembl3 GeneB Ensembl2
%h
с ключами GeneA, GeneB и т. д. => значения представляют собой ансамбли из File2. Обратите внимание, что при обработке File2 @ARGV имеет один элемент, поэтому @ARGV в скалярном контексте возвращает значение true. awkрешение:
awk 'NR==FNR{ a[$1]=$2; next }
{ $1=$1 FS (($1 in a)? a[$1]:"NA"); $2=$2 FS (($2 in a)? a[$2]:"NA"); }1' File2 File1
Вывод:
GeneA Ensembl1 GeneB Ensembl2
GeneA Ensembl1 GeneD NA
GeneC Ensembl3 GeneB Ensembl2