Thread Nur einen Buchstaben in Buchstabenkombination ersetzen (15 answers)
Opened by Gast at 2012-11-17 17:22

FIFO
 2012-11-18 08:54
#163359 #163359
User since
2005-06-01
469 Artikel
BenutzerIn

user image
Dein zweites Problem hätte mit dem Skript schon funktioniert, wäre dieses fehlerfrei gewesen ;) Die Bearbeitung von $pattern in der sub muss in drei Schritte zerlegt werden (vgl. edit).

Deine erste Frage ist ein Fall für tr///, allerdings musst Du beachten, dass hier keine Variableninterpolation stattfindet, daher die eval-Konstruktion. Um diesen Sonderfall abzubilden, werden die Kategorien erst in einem Hash abgelegt, so dass man aus den keys ein Suchmuster bauen kann, das alle Kategorie-Typen enthält.
Jetzt kannst Du natürlich jeden Sonderfall einzeln programmieren. Sinnvoll wäre es, zuerst die Benutzerschnittstelle (erlaubte Eingaben) wirklich festzulegen. Einzelfall-Programmierung ist immer schlecht zu ändern/erweitern.

Alles ist nach wie vor ohne Fehlerprüfungen! Es ist insbesondere sehr problematisch, User-Eingaben direkt als RegEx zu verwenden, wer böse ist, kann Dir hier einiges ruinieren. Ein gescheites Parsen der Eingaben ist also unabdingbar! btw: Was machst Du, wenn "normale" Großbuchstaben mit Deinen Kategorien kollidieren?

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use warnings;
use strict;

$| = 1;

my @categories = (
    'V=aeiou',
    'P=pbtdkg',
    'N=12345'
);

my %categ_hash     = map { split /=/ } @categories; #   ('V' => 'aeiou', ...)
my $categ_types    = join('', keys %categ_hash);    #   'VPN'
my $categ_types_rx = qr{ \A [$categ_types] \z }x;   #   \A[VPN]\z

while (1) {
    print "Text: ";
    my $text = <STDIN>;
    chomp($text);
    last if ! $text;

    print "Regel: ";
    my $rule = <STDIN>;
    chomp($rule);
    last if ! $rule;

    my $rule_err = rule_check($rule);
    if ($rule_err) {
        print "Regel fehlerhaft: $rule_err\n";
        next;
    }
     
    my $processed_text = process_text($text, $rule);

    print "\nNach Ersetzung: $processed_text\n\n";
}

sub rule_check {
    my $rule = shift;

    # Hier Regelsyntax prüfen!
    return 0;   # fehlerfrei
}

sub process_text {   # build_regex($rule);
    my ($text, $rule) = @_;

    my ($to_replace, $replace_with, $pattern) = split('/', $rule);

    my $processed = $text;

    # Sonderfall translate (z.B. Regel V/N/_), das $pattern wird ignoriert
    if ($to_replace =~ $categ_types_rx and $replace_with =~ $categ_types_rx) {
        $to_replace   = $categ_hash{$to_replace};
        $replace_with = $categ_hash{$replace_with};

        print ("tr/$to_replace/$replace_with/\n");

        if (length($to_replace) != length($replace_with)){
            warn "Ungleiche Zeichenzahl in Kategorien.\n";
        }
        else {
            local $_ = $processed;
            eval "tr/$to_replace/$replace_with/";
            $processed = $_;
        }
        return $processed;
    }

    for my $category (@categories) {
        my ($type, $class) = split('=', $category);

        $pattern =~ s/$type/[$class]/g;
        $to_replace =~ s/$type/[$class]/g;
    }
    $pattern =~ s/(.+)_/(?<=$1)_/;
    $pattern =~ s/_(.+)/_(?=$1)/;
    $pattern =~ s/_/$to_replace/;

    $processed =~ s/$pattern/$replace_with/g;
    return $processed;
}
__END__


Alles wie gesagt noch sehr schlicht. Denkbar wären z.B. noch Regeln wie V/N/_P (bislang wird das '_P' ignoriert, viel Spaß beim Programmieren :)

Beispiele:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
Text: mater
Regel: V/N/_
tr/aeiou/12345/

Nach Ersetzung: m1t2r

Text: amna
Regel: [sm]//_[mn]

Nach Ersetzung: ana


Editiert von FIFO: typo
Last edited: 2012-11-18 09:06:41 +0100 (CET)
Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? -- Brian Kernighan: "The Elements of Programming Style"

View full thread Nur einen Buchstaben in Buchstabenkombination ersetzen