Я предположил, что извлеченные строки региона следуют за строками CDS для каждого выравнивания.
Скопируйте этот код в script.pl:
use strict;
use warnings;
my $input = 1;
my @field = ('CDS','extracted region');
my (%data);
my (%counter);
&zero;
while ( <> ) {
## Omit header.
next if $. == 1;
next if $. == 2;
## Remove last '\n'.
chomp;
## Split line in tabs.
my @f = split /\t/;
## Is loop over?
if ( $f[2] =~ /$field[0]/ && $counter{$field[1]} > 1 )
{
&comparing;
&zero;
}
## Count number of $field[0] and $field[1] line
$counter{$f[2]}++;
## Storing data
@{$data{$f[2]}[$counter{$f[2]}]} = @f;
}
&comparing;
sub zero {
$data{$field[0]} = [];
$data{$field[1]} = [];
$counter{$field[0]} = 0;
$counter{$field[1]} = 0;
}
sub comparing {
## Is same line ($field[0] and $field[1])? if ( $input == 1 )
if ( $counter{$field[0]} == $counter{$field[1]} || $input == 2 )
{
&recover;
&stamp;
}
}
sub recover {
my $pos = &input2(0,0) if ( $input == 2 );
for my $i ( 1 .. $#{ $data{$field[0]} } ) {
&input1($i) if ( $input == 1 );
&input2($i,$pos) if ( $input == 2 );
}
}
sub input1 {
#;Extracted interval="376914 -> 377067"
$data{$field[1]}[$_[0]][8] =~ m/;Extracted interval="(\d+) /;
$data{$field[0]}[$_[0]][3] = $1;
$data{$field[1]}[$_[0]][8] =~ m/;Extracted interval="\d+ -> (\d+)"/;
$data{$field[0]}[$_[0]][4] = $1;
}
sub input2 {
if ( $_[0] == 0 )
{
#;Extracted interval="2010140 <- 2024072"
$data{$field[1]}[1][8] =~ m/;Extracted interval="(\d+) /;
$1;
}
else
{
$data{$field[0]}[$_[0]][3] = $_[1] + $data{$field[0]}[$_[0]][3];
$data{$field[0]}[$_[0]][4] = $_[1] + $data{$field[0]}[$_[0]][4];
}
}
sub stamp {
for my $i ( 1 .. $#{ $data{$field[0]} } ) {
for my $j ( 0 .. $#{ $data{$field[0]}[$i] } ) {
print "$data{$field[0]}[$i][$j]\t";
}
print "\n";
}
}
Вы могли запустить скрипт жемчуга с input1.txt:
perl script.pl input1.txt > output1.txt
если Вы изменяете строку:
my $input = 1;
с
my $input = 2;
Вы могли запустить скрипт жемчуга с input2.txt:
perl script.pl input2.txt > output2.txt
Сценарий Perl мог также получать два аргумента: входной файл и тип [12].
Править
В https://stackoverflow.com/questions/1730333/how-do-i-use-getoptions-to-get-the-default-argument существуют некоторые методы, собирающиеся получать аргументы.
Если Вы изменяете строку:
my $input = 1;
с
my $input = 1;
$input = $ARGV[1] if defined $ARGV[1];
Вы могли запустить скрипт жемчуга с input1.txt:
perl script.pl input1.txt > output1.txt
или
perl script.pl input1.txt 1 > output1.txt
и Вы могли запустить скрипт жемчуга с input2.txt:
perl script.pl input2.txt 2 > output2.txt
Нет общей функции, которая сделает a vlookup
как общая функция в Unix. Скорее Вы даете "кирпичи", из которых можно создать решения проблем в более специализированном подходе. Эти "кирпичи" являются инструментами такой как grep
, awk
, и sed
среди других.
Один из инструментов, awk
мог использоваться следующим образом:
FNR==NR{
a[$1]=$2
next
}
{ if ($1 in a) {print $1, a[$1]} else {print $1, "NA"} }
$ awk -f vlookup.awk file2 file1
1GR_P1:001PI 1GR_P1:001PI
:040VG_L1 NA
:001PO_L3 NA
1JPI_P1:001PO_L1 1JPI_P1:001PO_L1
1JPI_P1:001PO_L2 1JPI_P1:001PO_L2
Можно использовать column
управляйте к очистке выводом:
$ awk -f vlookup.awk file2 file1 | column -t
1GR_P1:001PI 1GR_P1:001PI
:040VG_L1 NA
:001PO_L3 NA
1JPI_P1:001PO_L1 1JPI_P1:001PO_L1
1JPI_P1:001PO_L2 1JPI_P1:001PO_L2
Вышеупомянутое awk
сценарий берет все содержание file2 в массив, который индексируется с помощью значения в качестве ключа.
a[$1]=$1
Однажды file2
был считан в массив a
, file1
затем не стал через строку за один раз, и решение принято. Если значение первого столбца file1
присутствует в массиве a
, затем соответствующее значение в file2
столбец 2 печатается наряду с file1
столбец 1. Если это не присутствует затем, сообщение "NA" печатается.
Для определенных примеров данных Вы обеспечили, следующее должно работать. Это загружает поле 2 из File2
в массив, индексированный полем 1. File1
затем циклично выполняется через и соответствия массива или NA
печатаются
awk 'NR == FNR{a[$1] = $2;next}; {print $1, $1 in a?a[$1]: "NA"}' File2 File1
POSIX join(1)
команда делает что-то очень похожее на VLOOKUP()
, с протестом, что входные файлы должны уже быть отсортированы на столбцах, к которым присоединятся.
$ sort file1 > sfile1
$ sort file2 > sfile2
$ join -a1 sfile1 sfile2
1GR_P1:001PI 1402UC
1JPI_P1:001PO_L1 1401UC
1JPI_P1:001PO_L2 1401UC
:001PO_L3
:040VG_L1
К сожалению, Ваш пример действительно не иллюстрирует как join
работы, с тех пор file1
содержит всего один столбец.
Для получения точно вывода, Вы хотите, Вы могли записать простой сценарий с помощью ассоциативных массивов, с помощью awk
например, как другие предположили.
Если Вы ищете что-то, что работает из командной строки, взглянули на awk
. Это - ОЧЕНЬ популярная программа, используемая для всех видов парсинга операций. http://en.wikipedia.org/wiki/AWK
Кроме того, трудно упомянуть, что анализировало текст в UNIX без упоминания grep
. grep
используется для regex совпавшего текста. В то время как не нужный для этого конкретного приложения это в конечном счете пригодится при выполнении большого текстового парсинга. http://en.wikipedia.org/wiki/Grep
Используя colrm
столбцы текста могут быть сокращены из потока. Это может быть полезно при наличии затруднений при изоляции текста с awk
.
sed
то, что Вы захотите использовать, если текст для парсинга будет очень длинен или если awk не может легко выполнить то, что Вы хотите. Sed на Википедию
Я уверен, что пропускаю десятки, но все, в чем Вы будете нуждаться для этого примера, awk
таким образом, Вы установлены.
Попробуйте смесь awk и советов (чрезвычайно быстрое хранилище значения ключа NoSQL с открытым исходным кодом. См. http://redis.io для деталей).
Используйте awk для парсинга Ваших 2 файлов для генерации команд советов.
Передайте результат по каналу 2 awk сценариев в удар для выполнения их. Вот именно :-)
Шаг за шагом:
Генерируйте свои операторы "SET" советов путем парсинга "File2" как это:
awk '{print "redis-cli SET KEY:" $1 " \"" $2"\""}' File2
redis-cli SET KEY:1JPI_P1:001PO_L1 "1401UC"
redis-cli SET KEY:1JPI_P1:001PO_L2 "1401UC"
redis-cli SET KEY:1HIK_P2:001ER "1402UC"
redis-cli SET KEY:1GR_P1:001PI "1402UC"
Передайте свои сгенерированные операторы "SET" советов по каналу в удар для выполнения их:
awk '{print "redis-cli SET KEY:" $1 " \"" $2"\""}' File2 |\
bash
OK
OK
OK
OK
Генерируйте свои операторы "GET" советов путем парсинга "File1" как это:
awk '{print "printf \"" $1 " \" && redis-cli GET KEY:" $1}' File1
printf "1GR_P1:001PI " && redis-cli GET KEY:1GR_P1:001PI
printf ":040VG_L1 " && redis-cli GET KEY::040VG_L1
printf ":001PO_L3 " && redis-cli GET KEY::001PO_L3
printf "1JPI_P1:001PO_L1 " && redis-cli GET KEY:1JPI_P1:001PO_L1
printf "1JPI_P1:001PO_L2 " && redis-cli GET KEY:1JPI_P1:001PO_L2
Теперь запросите советы путем передачи по каналу операторов "GET" советов, сгенерированных выше в удар:
awk '{print "printf \"" $1 " \" && redis-cli GET KEY:" $1}' File1 |\
bash
1GR_P1:001PI "1402UC"
:040VG_L1 (nil)
:001PO_L3 (nil)
1JPI_P1:001PO_L1 "1401UC"
1JPI_P1:001PO_L2 "1401UC"
Остерегайтесь этого, необходимо ли выйти из двойных кавычек в строках с единственными обратными косыми чертами, чтобы избежать, чтобы советы импортировали ошибки (см. ответ slm в том, Как я изменяю это решение для Perl так, чтобы это заменило встроенными двойными кавычками с одинарными кавычками?). Можно также использовать одинарные кавычки для инкапсуляции значений для импорта в советы, если значения содержат много двойных кавычек.
HTH
bernie
a[$1]=$1
кому:a[$1]=$2
– iruvar 28.08.2013, 18:10$1
column1 и$2
column2? Или каково различие междуa[$1]=$1
иa[$1]=$2
– HattrickNZ 18.08.2015, 06:07$1
и$2
вvlookup.awk
столбцы, но мы только устанавливаемa[$1]==$2
когда FNR равен НОМЕРУ. Посмотрите этот пример на ТАК для лучшего описания этого использования методаawk
: stackoverflow.com/questions/15065818/compare-files-with-awk. – slm♦ 18.08.2015, 08:31