• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Gelöst RegEx für Dateinamen - ich krieg's einfach nicht hin ...

Hallo allerseits,

ich brauche Hilfe beim erstellen von RegEx-Ausdrücken, mit denen ich Dateinamen filtern kann. Folgende Bedingungen:

Fall 1:
Dateiname (beliebige Länge, bestehend aus Buchstaben und Ziffern, auch Umlaute) soll genau 2 Punkte enthalten und der Teil nach dem zweiten Punkt soll "def" lauten.
Beispiele:
dateiname_wurbel_mit_schlonz_345.abc.def soll gefunden werden
dateiname_wurbel_mit_schlonz_345.abc.DEF soll gefunden werden
dateiname_wurbel_mit_schlonz_345.abc.dex soll ignoriert werden.

Fall 2:
Dateiname (beliebige Länge, bestehend aus Buchstaben und Ziffern, auch Umlaute) soll genau 2 Punkte enthalten, zwischen den Punkten soll eine bestimmte Anzahl Zeichen sein (alles mögliche), der Teil nach dem zweiten Punkt soll "xyz" lauten.
Beispiele mit 5 Zeichen zwischen den Punkten:
dateiname.abcde.xyz soll gefunden werden
dateiname.Ü_Ö_Ä.XYZ soll gefunden werden
dateiname.a_b_c.qqq soll ignoriert werden
dateiname.abc.xyz soll ignoriert werden

Ich bitte um Eure Hilfe!
 
Bei RegEx bin ich mir nie sicher, ob das auch wirklich das findet, was ich da eingebe. Oft gibt es ein Problem mit "Gier".
Ich würde nicht versuchen, alles in eine RegEx zu packen, und also das ganze Problem in der RegEx-Sprache zu lösen. Ich würde die Strings zerteilen, z.B. bei ".", und dann z.B. in "Fall 2" den Teilstring auf die richtige Anzahl von Zeichen untersuchen. Es würde bei mir also ein Programm, das aus mehr als nur einer (unlesbaren) RegEx-Zeile bestehen würde.
Natürlich würde ich das nicht mit sed oder sowas in bash machen, sondern z.B. in Perl. Mit einem etwas längeren Perl-Skript also. Da hätte ich die erforderliche Kontrolle.
Leider sagen Threadersteller hier seit vielen Jahren dann aber meistens "Ich kann aber kein Perl, und will das auch nicht lernen". Ja, schade.
 
Proof of concept, Fall 2:
Code:
#!/usr/bin/perl

use warnings;
use strict;

sub removeVowels {
    my $a = shift;
    my @b = qw/ä ö ü Ä Ö Ü ß/;
    my $i;
    for $i (@b) {
        $a =~ s/\Q$i\E/0/g;
    }
    return $a;
}

sub checkString {
    my $a = shift;
    my $numchars = shift;
    my $suf = shift;
    my @b = split(/\./, $a);
    if ($#b != 2) {
        print "Reason: Not exactly two points in string.\n";
        return 0;
    }
    my $c = removeVowels($b[1]);
    if (length($c) != $numchars) {
        print "Reason: Incorrect number of characters in '$b[1]'.\n";
        return 0;
    }
    if ($b[2] ne $suf && $b[2] ne uc($suf)) {
        print "Reason: Wrong suffix: '$b[2]'.\n";
        return 0;
    }
    return 1;
}

my @a = ("dateiname.abcde.xyz",
         "dateiname.Ü_Ö_Ä.XYZ",
         "dateiname.a_b_c.qqq",
         "dateiname.abc.xyz");

my $i;
for $i (@a) {
    print "$i\n";
    if (checkString($i, 5, "xyz")) {
        print "Result: Found.\n";
    } else {
        print "Result: Nope.\n";
    }
    print "\n";
}
 
Zuletzt bearbeitet:

framp

Moderator
Teammitglied
Bash:
#!/bin/bash

REGEX1=".+\..+\.def"
REGEX2=".+\..{5}\.xyz"

# Prefix teststring with either 0 (match expected) and 1 (no match expected) 
TEST_STRINGS1="1dateiname_wurbel_mit_schlonz_345.abc.def 1dateiname_wurbel_mit_schlonz_345.abc.DEF 0dateiname_wurbel_mit_schlonz_345.abc.dex"
TEST_STRINGS2="1dateiname.abcde.xyz 1dateiname.Ü_Ö_Ä.XYZ 0dateiname.a_b_c.qqq 0dateiname.abc.xyz"

errors=0
success=0

function check() { 
    echo
    echo "Testing $2 ..."
    for s in $1; do
        str=${s:1}
        res=${s:0:1}
        grep -E -i -q "$2" <<< "$str"
        rc=$?
        if (( ! $rc )); then
            echo -n "$str matches"
        else
            echo -n "$str does not match"
        fi
        
        if (( $rc != $res )); then
            echo " -> OK :-)"
            (( success ++ ))
        else
            echo " -> FAIL :-("
            (( errors ++ ))
        fi
    done
}    

check "$TEST_STRINGS1" "$REGEX1"
check "$TEST_STRINGS2" "$REGEX2"

if (( errors > 0 )); then
    echo "$errors tests failed"
else
    echo "All $success tests finished successfully"
fi

Code:
framp@majestix:~/scripts$ ./regex.sh 

Testing .+\..+\.def ...
dateiname_wurbel_mit_schlonz_345.abc.def matches -> OK :-)
dateiname_wurbel_mit_schlonz_345.abc.DEF matches -> OK :-)
dateiname_wurbel_mit_schlonz_345.abc.dex does not match -> OK :-)

Testing .+\..{5}\.xyz ...
dateiname.abcde.xyz matches -> OK :-)
dateiname.Ü_Ö_Ä.XYZ matches -> OK :-)
dateiname.a_b_c.qqq does not match -> OK :-)
dateiname.abc.xyz does not match -> OK :-)
All 7 tests finished successfully
 
Zuletzt bearbeitet:
Hallo !
Besten Dank an alle! Das mit Perl werde ich mir mal überlegen. Die beiden RegEx-Strings lösen aber das Problem, ohne dass ich jetzt viel ändern muss.
 
Oben