Thread Reguläre Ausdrücke suchen (34 answers)
Opened by Bionerd at 2012-04-18 12:19

topeg
 2012-04-19 11:36
#157635 #157635
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Wenn ich mir Ansehe, wie du meine Ergänzungen eingesetzt hast, so wundere ich mich doch etwas darüber. Du schiebst doch, das du schon eine Programmiersprache beherrschst.

Hier der Code der macht was du willst:
more (31.8kb):
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/perl
use strict;
use warnings;

my $dir='.';
my @motives = ("PO", "OHO", 'G[A-Z]{2}G');
my $out_dir='out';

my %anzahl;

# Ordner öffnen und durchgehen
opendir(my $dh, $dir) or die("Error open $dir,($!)\n");
while(my $file=readdir($dh))
{
  # Pfad machen.
  my $path="$dir/$file";

  # testen ob es eine Datei ist
  next unless(-f $path);
  next if($path!~/\.txt$/);

  print "Analyse File $file\n";
  my @found=analyse_file($path,\@motives);

  for my $e (@found)
  {
    my ($motive1,$motive2)= sort @$e[0,1];

    # für die Zusammenfassung
    $anzahl{join('-!-', $motive1,$motive2)}++;

    # Ausgabe in Konsole
    #printf ( qq("%s" and "%s" found in Line %u and Line %u\n),@$e );

    # Ausgabe in Datei
    my $outpath="$out_dir/$motive1$motive2.txt";
    if(open(my $fh, '>>', $outpath))
    { printf $fh ("%s + %s found in Line %u and Line %u + %s\n", @$e,$file); }
    else
    { warn("Error open $outpath ($!)"); }
  }
}
closedir($dh);

# Zusammenfassung
printf ("%s+%s %u\n",split(/-!-/,$_),$anzahl{$_}) for (sort keys(%anzahl));

########################################################################

sub analyse_file
{
  my $file=shift;
  my $motives=shift; # Referenz auf Array

  #die gesamte Datei einlesen
  my $content=read_file($file);
  unless($content)
  {
    warn("File empty!");
    return;
  }


  # eine Liste mit den Positionen der Zeileenden erstellen:
  my @line_ends=find_lineends($content);

  # alle Suchbegriffe durchgehen und sich alle Positionen merken.
  my %match;
  for my $motive (@$motives)
  {
    pos($content)=0;
    while($content=~/($motive)/g)
    {
      my $found=$1;
      # zur aktuellen Postion im String wird die Zeile Bestimmt
      my $line=calculate_line(\@line_ends,pos($content));

      # es wird ein Hash of Arrays erstellt
      push(@{$match{$found}},$line);
    }
  }


  # Auswertung
  my @found;
  my @keys=keys(%match);

  # jedes Fund mit jedem anderen Kombinieren
  # doppelte vermeiden
  for my $p1 (0..$#keys)
  {
    my $motive1=$keys[$p1];

    for my $p2 ($p1..$#keys)
    {
      my $motive2=$keys[$p2];

      next if($motive1 eq $motive2 and @{$match{$motive1}}<2);

      if($motive1 eq $motive2)
      {
        my @list=@{$match{$motive1}};
        for my $pos1 (0 .. $#list-1)
        {
          for my $pos2 ($pos1+1 .. $#list)
          {
            push(@found,[$motive1,$motive1,$list[$pos1],$list[$pos2]]);
          }
        }
      }
      else
      {
        for my $line1 (@{$match{$motive1}})
        {
          for my $line2 (@{$match{$motive2}})
          {
            push(@found,[$motive1,$motive2,$line1,$line2]);
          }
        }
      }
    }
  }
  return @found;
}

sub read_file
{
  my $file=shift;
  die("ERROR open $file ($!)\n") unless( open(my $handle, '<', $file) );
  #zeilenende auf undef setzen
  local $/=undef;
  # alles einlesen
  return <$handle>;
}

sub calculate_line
{
  my $endings=shift;
  my $pos=shift;
  return 0 if($pos<0);
  return $endings->[-1] if($pos > $endings->[-1]);
  for my $l (1..$#$endings)
  { return $l if($pos >= $endings->[$l-1] && $endings->[$l] >= $pos); }
  return -1;
}

sub find_lineends
{
  my $content=shift;
  my @list=(0);
  my $pos=0;
  while(( my $p=index($content,"\n",$pos) )>-1)
  {
    push(@list,$p);
    $pos=$p+1;
    last if($pos>=length($content));
  }
  return @list;
}


EDIT: Hatte den Wunsch nach dem Fund überlesen. Ist ergänzt.
Last edited: 2012-04-19 11:41:30 +0200 (CEST)

View full thread Reguläre Ausdrücke suchen