2017-02-13 6 views
0

Я задал вопрос о том, что раньше не было символа (X) в Perl. У меня теперь есть рабочий код, но это не работает, где чтение файлов.Perl - Соответствие с условиями ухода и чтением файлов csv

Предположим, у меня есть 50-битный двоичный вход и база данных. Если вход согласован с данными в базе данных, я вернул бы предопределенное значение.

Предположим, что данные в базе данных 11001100100010110111110110101001000010110101111101.

Если вход 11XX11001000101101111101101010010000101101011111X1, я хотел бы сказать, что это согласованный случай, поскольку X может быть 1 или 0. Я знаю способ разделить 50 бит в 50 1 бит и сделать исключение, но я бы предпочел для обработки 50-бит вместе.

В моем коде (dontcare.pl) первая часть работает с внутренне определенными входами и базой данных. Тем не менее, я хотел бы прочитать входной файл (input_text.txt) и файл базы данных (database.txt), который содержит другую информацию и делает то же самое.

dontcare.pl:

#!/usr/bin/perl 

####### 1st part, Internal string input and database 
my $input = '11XX11001000101101111101101010010000101101011111X1'; 
(my $mask = $input) =~ tr/X01/\x00\xFF\xFF/; 
(my $targ = $input) =~ tr/X/\x00/; 

for my $num_bin (qw(
    11001100100010110111110110101001000010110101111101 
    10101100100010110111110110101001000010110101111101 
)) { 
    if (($num_bin & $mask) eq $targ) { 
     print "$num_bin matches\n"; 
    } else { 
     print "$num_bin doesn't match\n";  
    } 
} 


####### 2nd part, Reading input and database files 
     print " Reading files\n";  
##### Read input 
my @Dinput=do{ 
    open my $Dfh,"<","input_test.txt" or die("Cannot open an input file $!"); 
    <$Dfh>; 
}; 

##### Read database 
open(CSV,'database.txt')||die("Cannot open db file $!"); 
my @Ddb; 

while(<CSV>){ 
    my @row=split(/\t/,$_); 
    push(@Ddb,\@row); 
} 
close CSV || die $!; 


for (my $n=0; $n < (scalar @Dinput); $n +=1) { 

for (my $i=0; $i < (scalar @Ddb); $i +=2) { 
    (my $Dmask = $Dinput[$n]) =~ tr/X01/\x00\xFF\xFF/; 
    (my $Dtarg = $Dinput[$n]) =~ tr/X/\x00/; 

    if (($Ddb[$i][1] & $Dmask) eq $Dtarg) { 
     print "$Ddb[$i][1] matched\n"; 
    } else { 
     print "$Ddb[$i][1] didn't match\n";  
    } 
} 

} 

input_test.txt: (входной файл, содержащий два входа)

11XX11001000101101111101101010010000101101011111X1 
1000011000111101001011110111001100100101111000010X 

database.txt:. (Файл базы данных имеет 50-битный двоичный в второй столбец. Другая информация также содержится в файле)

0.1 11001100100010110111110110101001000010110101111101 rml_irf_old_e_cwp_e[1] rml_irf_new_e_cwp_e[1] rml_irf_swap_even_e rml_irf_old_e_cwp_e[0] rml_irf_new_e_cwp_e[0] rml_irf_swap_odd_e 
0.1 11101100110010011011001101100111001001100000010011 3.923510310023e-06 3.19470818154393e-08 7.05437377900141e-10 7.05437377900141e-10 4.89200539851702e-17 5.01433479478681e-19 
0.1 10000110001111010010111101110011001001011110000100 rml_irf_new_e_cwp_e[1] rml_irf_new_e_cwp_e[0] 
0.1 01110111010010000000101001000001100011011100011111 0.052908822741908 2.7185508579738e-05 

Я думаю, что это проблема с литьем типа. Первая часть содержит строку ввода и строку базы данных, поэтому она работает. Однако вторая часть автоматически считывает ввод и данные из файлов как целые числа. Я искал тип кастинга и понял, что в Perl нет функции кастинга (или я ошибаюсь). Пожалуйста, дайте мне знать любую идею и/или рекомендацию для решения этой проблемы.

Вкратце, я хотел сделать совпадение с условием невращения работы с файлами ввода и базы данных. Пожалуйста, дайте мне знать, если у вас есть другие способы работать с этим. (Я использовал временное изменение значения во входном файле).

+0

Ваш вход фактически двоичным, или это ASCII строки 1 и 0? (если вы 'cat', вы получаете выше выход?) – Sobrique

+0

Это строка. –

ответ

3

Ну, набирайте литье - этого не существует, как вы думаете, потому что perl на самом деле не заботится о том, что-то строка или число - это правильная вещь в зависимости от контекста.

Тем не менее, есть такие вещи, как pack и unpack, которые преобразуют необработанные двоичные данные в более полезное представление. Например. от (raw) двоичного до шестнадцатеричного и обратно. Они, похоже, не применяются, потому что ваш вход не двоичный - это просто текст.

Но я должен сказать, - я думаю, что вы решение этого более трудный путем, чем нужно (если я не недопонимание вашей проблемы), и вы на самом деле не нужно делать бинарное этому перенос на все:

#!/usr/bin/perl 

use warnings; 
use strict; 

#or read this from a file 
my @input = qw (11XX11001000101101111101101010010000101101011111X1 
       1000011000111101001011110111001100100101111000010X); 
#replace 'X' with '.' which is the regex "don't care" character.     
s/X/./g for @input; 
#compile a regex made of these two patterns. 
my $search = join ("|", @input); 
    $search = qr/$search/; 

print "Compiled input patterns into a regex of: \n"; 
print $search,"\n"; 

#iterate database (pasted in 'data' block for illustrative purposes) 
while (<DATA>) { 
    my ($id, $target, @rest) = split; #split on whitespace. 
       # you are using tab sep, so you might prefer split /\t/; 
    #field 1 = ID 
    #field 2 = $target 
    #everything else = @rest 
    #compare $target with the regex we compiled above, and print the 
    #current line if it matches. 
    print if $target =~ /$search/; 
} 


__DATA__ 
0.1 11001100100010110111110110101001000010110101111101 rml_irf_old_e_cwp_e[1] rml_irf_new_e_cwp_e[1] rml_irf_swap_even_e rml_irf_old_e_cwp_e[0] rml_irf_new_e_cwp_e[0] rml_irf_swap_odd_e 
0.1 11101100110010011011001101100111001001100000010011 3.923510310023e-06 3.19470818154393e-08 7.05437377900141e-10 7.05437377900141e-10 4.89200539851702e-17 5.01433479478681e-19 
0.1 10000110001111010010111101110011001001011110000100 rml_irf_new_e_cwp_e[1] rml_irf_new_e_cwp_e[0] 
0.1 01110111010010000000101001000001100011011100011111 0.052908822741908 2.7185508579738e-05 

Это то, для вашей базы данных, печатает:

0.1 11001100100010110111110110101001000010110101111101 rml_irf_old_e_cwp_e[1] rml_irf_new_e_cwp_e[1] rml_irf_swap_even_e rml_irf_old_e_cwp_e[0] rml_irf_new_e_cwp_e[0] rml_irf_swap_odd_e 
0.1 10000110001111010010111101110011001001011110000100 rml_irf_new_e_cwp_e[1] rml_irf_new_e_cwp_e[0] 

с точкой зрения шаблонов для чтения из конкретного файла - наиболее вероятной причины, что бы разорвать, если вы забыли chomp моделей, как вы читаете их.

Таким образом, вы бы загрузить их, как это (проверено с приведенными выше данными):

#!/usr/bin/perl 

use warnings; 
use strict; 

#Read patterns from file 
open (my $input_fh, '<', 'patterns.txt') or die $!; 
chomp (my @input = <$input_fh>); 
close ($input_fh); 
#replace 'X' with '.' which is the regex "don't care" character.     
s/X/./g for @input; 
#compile a regex made of these two patterns. 
my $search = join ("|", @input); 
    $search = qr/$search/; 

#iterate database (pasted in 'data' block for illustrative purposes) 
open (my $data, '<', 'database.txt') or die $!; 
while (<$data>) { 
    my ($id, $target, @rest) = split; 
    #print if the target line matches 
    print if $target =~ /$search/; 
} 

именно с вашим кодом (и что из вашего ответа):

  • Включите use strict; use warnings; - это важно для устранения неполадок.
  • Вам не нужно использовать двойную петлю, потому что поворот ваших шаблонов ввода в переменное регулярное выражение делает это для вас (более эффективно).
  • Всегда используйте 3 arg open с лексическими файловыми дескрипторами. open (my $input_fh, '<', 'patterns.txt') or die $!, потому что дескриптор файла CSV является глобальным (и не закрывается автоматически, как лексический, когда он выходит из сферы действия).
  • $i < (scalar @Ddb) является избыточным. < делает его скалярным контекстом, поэтому вы можете просто $i < @db и получить тот же результат.
  • perltidy - это хорошо для форматирования кода. perltidy -pbp будет форматироваться на основе «лучших практик perl».
+0

Спасибо. В любом случае это хорошо для меня. Я думаю "." это то, что я хотел первоначально. Я изменил свой код, но, похоже, я не понял часть во время цикла правильно. Не могли бы вы объяснить подробности? Я добавлю свой код в следующем. Спасибо. –

+0

Проблема, которую вы испытываете при чтении, заключается в том, что вы не 'chomp' на входе, поэтому он имеет встроенные переводы строк. – Sobrique

+0

Кроме того, вам действительно не нужно открывать внутри вашего блока 'do'. Я подозреваю, что это означает, что вы получите код возврата 'open', загрязняющий ваш список. Попробуйте 'open my $ input_fh, '<', 'file.txt' или die $! ; chomp (my @input = <$input_fh>); ' – Sobrique

0

Спасибо за помощь - @Sobrique

Мой исходный код сделал мой код более сложным. То, что я хотел сделать, это на самом деле «.», Который является символом нежности и способ обработки этого символа. Кроме того, требуется чтение csv-файлов в качестве входных данных и базы данных. @sobrique очень помог мне решить все проблемы, и вот мой окончательный код.

мой код:

#!/usr/bin/perl 

##### Read input 

open my $input_fh, '<', 'input_test.txt' or die $! ; chomp (my @input = <$input_fh>); 

#replace 'X' with '.' which is the regex "don't care" character.     
s/X/./g for @input; 
#compile a regex made of these two patterns. 
#my $search = join ("|", @input); 
# $search = qr/$search/;  
my $search = join ("|", $input[0]); 
    $search = qr/$search/; 

##### Read database 
open(CSV,'database.txt')||die("Cannot open db file $!"); 
my @Ddb; 
while(<CSV>){ 
    my @row=split(/\t/,$_); 
    push(@Ddb,\@row); 
} 
close CSV || die $!; 


#iterate database (pasted in 'data' block for illustrative purposes) 
for (my $n=0; $n < (scalar @input); $n +=2) { 

for (my $i=0; $i < (scalar @Ddb); $i +=2) { 
    if ($Ddb[$i][1] =~ /$search/) { 
     print "$Ddb[$i][1] matched\n"; 
     print "$Ddb[$i][2] \n"; 
    } 
#else { 
#  print "$Ddb[$i][1] didn't match\n";  
#  } 
} 

} 

input_test.txt:

10001000110010001001110111000011001010110010000011 
10111101010011000101001011110000001110101110010011 
+0

Требуется' chomp' для удаления строки. – Sobrique

+0

Но это действительно должно быть редактирование ваших вопросов, потому что на самом деле это не ответ. – Sobrique

+0

Да, я уточню свой ответ. Я исправил проблему с вводом на основе ваших комментариев. Спасибо. –