Я бы сделал это на Perl, потому что в нем есть функция sort
, которая позволяет нам легко рассматривать A T
и T A
как одно и то же. Например, (показывает выходные данные для всех ваших примеров файлов вместе взятых):
$ perl -lane 'if(!$k){$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F[1]; }else{$var=join("", "chr".$F[1],$F[2],sort($F[3],$F[4])); $F[0]=$name{$var} if $name{$var};print join "\t", @F; } $k++ if eof' file2 file1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179_A_G 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
Или, чуть более разборчиво:
$ perl -lane 'if(!$k){
$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F[1];
}
else{
$var=join("", "chr".$F[1],$F[2],sort($F[3],$F[4]));
$F[0]=$name{$var} if $name{$var};
print join "\t", @F;
}
$k++ if eof' file2 file1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
perl -lane
:-a
заставляет Perl вести себя как awk, автоматически разбивая входные данные на массив @F
по пробелам. Поскольку массивы Perl начинаются с 0
, $F[0]
будет первым полем, $F[1]
будет вторым и т. д. Поле N равно $F[N-1]
. -n
заставляет perl читать свои аргументы как текстовые файлы и применять сценарий, заданный -e
, к каждой их строке. -l
просто удаляет завершающие символы новой строки из каждой входной строки и добавляет новую строку к каждому вызову print
.
$k++ if eof
:это увеличивает переменную $k
на 1, если мы достигли конца файла(eof
). Затем мы можем использовать if(!$k)
(, если $k не определен )как эквивалент NR==FNR
в awk.
if (!$k ){$name{join ("","chr".$F[0],$F[3],sort ($F[4], $F[5] ))}=$F[1];} : if this is the first file,
файл2 , join fields 1, 4, and the sorted fields 5 and 6, into a string and use that string as the key in the hash (associative array)
имя . Then, save the variant's name from file2 as the value associated with that key. The sorting lets us treat
AT and
TA as equivalent. I use
"chr".$F[0] to deal with cases like
1 123 and
11 23 `, где конкатенация хромосомы и положения дает одно и то же число, даже если хромосомы на самом деле разные.
else{
:если мы сейчас читаем второй файл, file1
.
$var=join("", $F[1],$F[2],sort($F[3],$F[4]));
:построить ключ. На этот раз с использованием полей 2, 3 и сортировки 4 и 5. $F[0]=$name{$var} if $name{$var};
:установить 1-е поле на значение, хранящееся в хеше name
, если есть значение для этого ключа. if
необходим, чтобы убедиться, что мы не меняем заголовок или какие-либо другие варианты, которые могут присутствовать в file1
, но не в file2
. print join "\t", @F;
:распечатать поля, включая только что внесенные изменения. с помощью bash...
find. -name '*.epub' | xargs basename -s.epub | xargs -I {} ebook-convert {}.epub {}.mobi ;
или, для имен файлов с пробелами...
find. -name '*.epub' -print0 | xargs -0 basename -s.epub | xargs -I {} ebook-convert "{}.epub" "{}.mobi" ;
ломая его...
find. -name '*.epub'
find. -name '*.epub' | xargs basename -s.epub
CMD='echo ebook-convert' && find. -name '*.epub' | xargs basename -s.epub | xargs -I {} $CMD "{}.epub" "{}.mobi" ;
опции -print0
и -0
заставляют эти команды использовать пустые значения вместо пробелов для разделения имен файлов.
-I
создает заполнитель {}
, который работает путем замены.
Ps :хотя это полезная техника, я также думаю, что Makefile (см. выше )является отличным решением для такого рода задач.
Я думаю, что вы можете сделать так же мило, как %.mobi: %.epub
из GNU make часть принятого ответа --без GNU make и его ограничений на имена файлов --с небольшой оболочкой:
from_to(){
sp=${1%%%*}; ss=${1#*%}; shift
dp=${1%%%*}; ds=${1#*%}; shift
for s in "$sp"*"$ss"; do
d=${s#"$sp"}; d=$dp${d%"$ss"}$ds
"$@" "$s" "$d" || exit 1
done
}
Который можно использовать как
from_to %.epub %.mobi ebook-convert
from_to dir1/book_%.epub dir2/%.mobi ebook-convert
Пример пробного теста:
% touch {1,2,3}.foo
% from_to./%.foo bar/%.baz echo translate --
translate --./1.foo bar/1.baz
translate --./2.foo bar/2.baz
translate --./3.foo bar/3.baz
В любом случае, вы должны использовать что-то другое, кроме *
, так как это имеет устоявшееся значение в оболочке Unix.