Как мне найти строку в файле с разными заголовками? - PullRequest
2 голосов
/ 27 апреля 2009

Я использую perl для поиска определенных строк в файле с разными последовательностями, перечисленными под разными заголовками. Я могу написать сценарий, когда есть одна последовательность, то есть один заголовок, но я не могу ее экстраполировать. Предположим, мне нужно найти строку "FSFSD" в данном файле, например: не может искать, если файл имеет следующее содержание :

Polons
CACAGTGCTACGATCGATCGATDDASD
HCAYCHAYCHAYCAYCSDHADASDSADASD
Seliems
FJDSKLFJSLKFJKASFJLAKJDSADAK
DASDNJASDKJASDJDSDJHAJDASDASDASDSAD
Teerag
DFAKJASKDJASKDJADJLLKJ
SADSKADJALKDJSKJDLJKLK

Может искать, когда файл имеет один заголовок, т.е.:

терран
FDKFJSKFJKSAFJALKFJLLJ
DKDJKASJDKSADJALKJLJKL
DJKSAFDHAKJFHAFHFJHAJJ

Мне нужно вывести результат как «Строка xyz , найденная под заголовком abc »

Код, который я использую:

print "Input the file name \n";
$protein= <STDIN>;
chomp $protein;
unless (open (protein, $protein))
{
print "cant open file \n\n";
exit;
}
@prot= <protein>;
close protein;
$newprotein=join("",@prot);
$protein=~s/\s//g;
do{
print "enter the motif to be searched \n";
$motif= <STDIN>;
chomp $motif;
if ($protein =~ /motif/)
{
print "found motif \n\n";
}
else{
print "not found \n\n";
}
}
until ($motif=~/^\s*$/);
exit;

Ответы [ 5 ]

4 голосов
/ 27 апреля 2009

Увидев ваш код, хочу сделать несколько предложений, не отвечая на ваш вопрос:

  1. Всегда, всегда, всегда use strict;. Ради любви к высшей силе, в которую вы можете (или не можете) верить, use strict;.
  2. Каждый раз, когда вы use strict;, вы должны use warnings; вместе с ним.
  3. Кроме того, серьезно подумайте об использовании отступов.
  4. Также рассмотрите возможность использования явно разных имен для разных переменных.
  5. Наконец, ваш стиль действительно противоречив. Это весь твой код или ты исправил его вместе? Не пытаюсь оскорбить вас или что-то еще, но я рекомендую не копировать код, который вы не понимаете - по крайней мере попробуйте , прежде чем просто скопировать его.

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

use strict;
use warnings;

print "Input the file name:\n";
my $filename = <STDIN>;
chomp $filename;
open FILE, "<", $filename or die "Can't open file\n\n";
my $newprotein = join "", <FILE>;
close FILE;
$newprotein =~ s/\s//g;
while(1) {
  print "enter the motif to be searched:\n";
  my $motif = <STDIN>;
  last if $motif =~ /^\s*$/;
  chomp $motif;
  # here I might even use the ternary ?: operator, but whatever
  if ($newprotein =~ /$motif/) {
    print "found motif\n\n";
  }
  else {
    print "not found\n\n";
  }
}
3 голосов
/ 27 апреля 2009

Основная проблема заключается в том, как вы отличаете заголовок от данных, из ваших примеров я предполагаю, что строка является заголовком если она содержит строчную букву.

use strict;
use warnings;
print "Enter the motif to be searched \n";
my $motif = <STDIN>;
chomp($motif);
my $header;
while (<>) {
    if(/[a-z]/) {
        $header = $_;
        next;
    }
    if (/$motif/o) {
        print "Found $motif under header $header\n";
        exit;
    }
}
print "$motif not found\n";
1 голос
/ 27 апреля 2009

Итак, вы говорите, что можете прочитать одну строку и выполнить эту задачу. Но когда у вас есть более одной строки в файле, вы не можете сделать то же самое?

Просто сделайте цикл и читайте файл построчно.

$data_file="yourfilename.txt";
open(DAT, '<', $data_file) || die("Could not open file!");
while( my $line = <DAT>)
{
 //same command that you do for one 'heading' will go here. $line represents one heading
} 
0 голосов
/ 27 апреля 2009
use strict;
use warnings;
use autodie qw'open';

my($filename,$motif) = @ARGV;

if( @ARGV < 1 ){
  print "Please enter file name:\n";
  $filename = <STDIN>;
  chomp $filename;
}

if( @ARGV < 2 ){
  print "Please enter motif:\n";
  $motif = <STDIN>;
  chomp $motif;
}

my %data;

# fill in %data;
{
  open my $file, '<', $filename;

  my $heading;
  while( my $line = <$file> ){
    chomp $line;
    if( $line ne uc $line ){
      $heading = $line;
      next;
    }
    if( $data{$heading} ){
      $data{$heading} .= $line;
    } else {
      $data{$heading}  = $line;
    }
  }
}

{
  # protect against malicious users
  my $motif_cmp = quotemeta $motif;

  for my $heading ( keys %data ){
    my $data = $data{$heading};

    if( $data =~ /$motif_cmp/ ){
      print "String $motif found under Heading $heading\n";
      exit 0;
    }
  }

  die "String $motif not found anywhere in file $filename\n";
}
0 голосов
/ 27 апреля 2009

РЕДАКТИРОВАТЬ: Вы опубликовали пример не имеет четкого разделителя, вам нужно найти четкое разделение между вашими заголовками и вашими последовательностями. Вы можете использовать несколько разрывов строк или не алфавитно-цифровые символы, такие как ','. Что бы вы ни выбрали, пусть WHITESPACE в следующем коде будет равен выбранному вами разделителю. Если вы застряли в имеющемся у вас формате, вам придется изменить следующую грамматику, чтобы игнорировать пробелы и разделять их заглавными буквами (это немного усложняет).

Простой способ (O (n ^ 2)?) - разделить файл, используя разделитель пробелов, давая вам массив заголовков и последовательностей (заголовок [i] = split_array [i * 2], sequence [i] = split_array [я * 2 + 1]). Для каждой последовательности выполните свое регулярное выражение.

Чуть более сложный способ (O (n)), учитывая грамматику БНФ, такую ​​как:

file: block
    | file block
    ;

block: heading sequence

heading: [A-Z][a-z]

sequence: [A-Z][a-z]

Попробуйте рекурсивный приличный анализ (псевдокод, я не знаю perl):

GLOBAL sequenceHeading, sequenceCount
GLOBAL substringLength = 5
GLOBAL substring = "FSFSD"

FUNC file ()
    WHILE nextChar() != EOF
        block()
        printf ( "%d substrings in %s", sequenceCount, sequenceHeading )
    END WHILE
END FUNC

FUNC block ()
    heading()
    sequence()
END FUNC

FUNC heading ()
    in = popChar()
    IF in == WHITESPACE
        sequenceHeading = tempHeading
        tempHeading = ""
        RETURN
    END IF
    tempHeading &= in
END FUNC

FUNC sequence ()
    in = popChar()
    IF in == WHITESPACE
        sequenceCount = count
        count = 0
        i = 0
    END IF
    IF in == substring[i]
        i++
        IF i > substringLength
            count++
        END IF
    ELSE
        i = 0
    END IF
END FUNC

Для получения подробной информации о рекурсивном приличном разборе, посмотрите Давайте создадим компилятор или Википедия .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...