Perl Regex синтаксис - PullRequest
       5

Perl Regex синтаксис

0 голосов
/ 29 июля 2010

Я хотел бы использовать Perl, чтобы взять ранее сгенерированный файл синтаксиса SPSS и отформатировать его для использования в среде R.

Это, вероятно, очень простая задача для тех, кто знаком с Perl и regex, но яя спотыкаюсь

Шаги, описанные мной для этого сценария Perl, следующие:

  1. Чтение в файле SPSS
  2. Поиск соответствующих фрагментов файла SPSS (регулярное выражение) для дальнейшей обработки и форматирования
  3. Дальнейшая обработка отмечена выше (больше регулярных выражений)
  4. Возврат синтаксиса R в командную строку или предпочтительно в файл.

Основной форматСинтаксис меток значений SPSS:

...A bunch of nonsense I do not care about...
...
 Value Labels
/gender
1 "M"
2 "F"
/purpose
1 "business"
2 "vacation"
3 "tiddlywinks"

execute . 
...Resume nonsense...

И желаемый синтаксис R, который мне нужен, выглядит следующим образом:

gender <- as.factor(gender
    , levels= c(1,2)
    , labels= c("M","F")
    )
...

Вот сценарий Perl, который я написал до сих пор.Я успешно прочитал каждую строку в соответствующий массив.У меня есть общий поток того, что мне нужно для окончательной функции печати, но мне нужно выяснить, как ТОЛЬКО печатать соответствующие массивы @levels и @labels для каждого массива @vars.

#!/usr/bin/perl

#Need to change to read from argument in command line
open(VARVAL, "append.txt");
@lines = <VARVAL>;
close(VARVAL);

#Read through each line and put into a variable, a value, or a reject
#I really only want to read in everything between "value labels" and "execute ."
#That probably requires more regex...
foreach  (@lines){
    if ($_ =~ /\//){        #Anything with a / is a variable, remove the / and push
        $_ =~ tr/\///d;
        push(@vars, $_)
    } elsif ($_ =~/\d/) {
        push(@vals, $_)    #Anything that has a number in the line is a value
        }
}
#Splitting each @vals array into levels or labels arrays
foreach (@vals){
    @values = split(/\s+/, $_); #Splitting on a space, vunerable...better to split on first non digit character?
    foreach (@values) {
        if ($_ =~/\d/){
            push(@levels, $_);
        } else {
            push(@labels, $_)
        }
    }
}

#Get rid of newline
#I should provavly do this somewhere else?
chomp(@vars);
chomp(@levels);
chomp(@labels);

#Need to tell it when to stop adding in @levels & @labels. While loop? Hash lookup?
#Need to get rid of final comma
#Need to redirect output to a file
foreach (@vars){
    print $_ ." <- as.factor(" . $_ . "\n\t, levels = c(" ;
         foreach (@levels){
            print $_ . ",";
         }
    print ")\n\t, labels = c(";
    foreach(@labels){
            print $_ . ",";
        }
    print ")\n\t)\n";
}

И, наконец,Вот пример выходных данных скрипта в его текущем состоянии:

gender <- as.factor(gender
    , levels = c(1,2,1,2,3,)
    , labels = c("M","F","biz","action","tiddlywinks",)
    )

Мне нужно включить только уровни 1,2 и метки M и F.

Спасибо за помощь!

1 Ответ

2 голосов
/ 29 июля 2010

Это, кажется, работает для меня:

#!/usr/bin/env perl
use strict;
use warnings;

my @lines = <DATA>;

my $current_label = '';
my @ordered_labels;
my %data;
for my $line (@lines) {
    if ( $line =~ /^\/(.*)$/ ) { # starts with slash
        $current_label = $1;
        push @ordered_labels, $current_label;
        next;
    }
    if ( length $current_label ) {
        if ( $line =~ /^(\d) "(.*)"$/ ) {
            $data{$current_label}{$1} = $2;
            next;
        }
    }
}

for my $label ( @ordered_labels ) {
    print "$label <- as.factor($label\n";
    print "    , levels= c(";
    print join(',',map { $_ } sort keys %{$data{$label}} );
    print ")\n";
    print "    , labels= c(";
    print join(',',
        map { '"' . $data{$label}{$_} . '"'  }
        sort keys %{$data{$label}} );
    print ")\n";
    print "    )\n";
}

__DATA__
...A bunch of nonsense I do not care about...
...
 Value Labels
/gender
1 "M"
2 "F"
/purpose
1 "business"
2 "vacation"
3 "tiddlywinks"

execute . 

И дает:

gender <- as.factor(gender
    , levels= c(1,2)
    , labels= c("M","F")
    )
purpose <- as.factor(purpose
    , levels= c(1,2,3)
    , labels= c("business","vacation","tiddlywinks")
    )
...