[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [gelöst]Re: /bin/sh: prüfen ob String1 "Wort" aus String2 enthält



Michael Lange:
> Jochen Spieker <ml@well-adjusted.de> wrote:
> 
> > Michael Lange:
> > > 
> > >     INSTALLED_PKGS=$(echo `apt-mark showauto` `apt-mark showmanual`)
> > >     PKGS=""
> > >     for p in $PKGNAMES; do
> > >         case " $INSTALLED_PKGS " in
> > >             *" $p "*)
> > >                 PKGS="$PKGS $p"
> > >             ;;
> > >         esac
> > >     done
> > >     PKGNAMES="$PKGS"
> > 
> > Als (ehemaliger) Softwareentwickler blutet mir dabei allerdings das
> > Herz. Das wird mit vielen Paketen sehr ineffizient.
> 
> Erstaunlicherweise nicht,

Doch, in der asymptotischen Betrachtung schon. :) Du baust den String 
PKGS pro Paket neu (n mal) und dabei wird er immer länger. Der erste 
Paketname wird n-1 mal kopiert, der zweite n-2 und so weiter. Das ist
einfach ein schlechter Algorithmus. Die Laufzeit steigt überproportional
zur Länge der Paketliste. Sowas will man grundsätzlich vermeiden.

Dein Ansatz, das mit pessimistischen aber realistischen Testdaten zu
messen ist aber genau richtig. Das schlägt jede Theorie (bis die
Annahmen über die Daten von der Realität überholt werden. ;-))

> allerdings brauchte es dafür noch eine kleine
> Änderung. Das fiel mir auf, als ich versuchte das obige mit posh laufen
> zu lassen, was dann zu etwas seltsamen Resultaten führte. Die Lösung war
> schliesslich, das ganze folgendermassen zu ändern:
> 
> PKGS=""
> for p in "$PKGNAMES"; do
>     case " $INSTALLED_PKGS " in
>         *" $p "*)
>            PKGS="$PKGS $p";;
>     esac
> done
> PKGNAMES="$PKGS"

Der Unterschied, den ich sehe ist, dass Du im Schleifenkopf $PKGNAMES
gequotet hast. Wenn mich nicht alles täuscht, dann iteriert die Schleife
damit nur noch genau einmal. Überprüf mal, ob das noch richtig
funktioniert.

> Die von dir und Christian vorgeschlagenen Varianten mit "comm" und
> "uniq" brauchen mit bash jew. ca. 7/100 Sek., mit dash ca. 4/100, egal
> wie gross PKGNAMES ist. Ich vermute, das ist die Zeit, die die Shell
> benötigt, um die Subshell zu starten und das Programm aufzurufen, und das
> Programm selbst erledigt die Arbeit dann praktisch in 0,nix .

… für so "kleine" Eingabemengen, ok.

> Die "case" Variante benötigte in der Version ohne die Anführungszeichen
> um $PKGNAMES mit bash ca. 8 Sek. , mit dash ca. 1 Sek. .
> Mit den Anführungszeichen allerdings braucht die bash dann nur noch 2/100
> Sek. , die dash schaffte es laut time in 0,00 Sek. !

for p in "a b c"; do
    echo $p
done

=>
a b c


for p in a b c; do
    echo $p
done

=>
a
b
c

Das eine ist ein Durchlauf, weil der String "a b c" durch das Quoting
nicht nach den üblichen Regeln aufgeteilt wird. Ohne Quotes sind das
drei Worte und für jedes wird die Schleife durchlaufen.

J.
-- 
A passionate argument means more to me than a blockbuster movie.
[Agree]   [Disagree]
                 <http://archive.slowlydownward.com/NODATA/data_enter2.html>

Attachment: signature.asc
Description: Digital signature


Reply to: