Johannes Weißl: Mit Perl den ASCII-Wert eines Zeichens ändern

Hallo,

Wie kann man mit Perl den ASCII-Wert eines Zeichens ändern?
(z.B. um A hat den Wert 65 und dieser Wert soll um 5 nach unten gesetzt werden und dieser Wert, also 60, soll wieder in ein Zeichen verwandelt werden!)

cu,
Johannes

  1. Hi,

    Wie kann man mit Perl den ASCII-Wert eines Zeichens ändern?

    wie lange hast Du Zeit, um Dir alle Möglichkeiten anzuhören?

    (z.B. um A hat den Wert 65 und dieser Wert soll um 5 nach unten gesetzt werden und dieser Wert, also 60, soll wieder in ein Zeichen verwandelt werden!)

    $string =~ s/A/chr(60)/eg;

    Je nach Anforderungen tun es auch substr, tr///, pack usw. Schau in der Doku zum jeweiligen Befehl nach.

    Cheatah

    1. Hi,

      $string =~ s/A/chr(60)/eg;

      viel zu statisch, besser so in der Richtung:

      $string =~ s/(.)/chr(ord($1)-5)/eg;

      mfg
      CK1

      1. Hallo

        $string =~ s/A/chr(60)/eg;

        viel zu statisch, besser so in der Richtung:
        $string =~ s/(.)/chr(ord($1)-5)/eg;

        mag sein, aber verstehen, wenn man bei regexpr. das überhaupt sagen kann ;-) tut man cheatahs Version am ehesten! Bei deiner steigt jeder nicht-auch-nur-halbwegs-perl-Profi wie ich leider voll aus :-(

        Dazu müsste man erst mal wissen, was (.) matcht (Irgendein einzelnes Zeichen?)
        und was in $1 drinnenliegt (der gematchte Asudruck??)

        ... dann könnte ich mir daraus einen halbwegs sinnvollen ;-) Reim machen!

        Übrigens, an welcher Ascii-Tabelle orientiert sich Perl, wenn man chr(xxx) aufruft? Da sind ja die Zeichenbelegungen ziemlich unterschiedlich, zumindest bei den Sonderzeichen! Gibts da einen Standardzeichensatz?

        liebe Grüsse und,
        keep it simple ;-)
        Bernhard

        1. Hi,

          $string =~ s/(.)/chr(ord($1)-5)/eg;

          mag sein, aber verstehen, wenn man bei regexpr. das überhaupt sagen kann ;-) tut man cheatahs Version am ehesten!

          Christians Lösung ist nur eine kleine Verallgemeinerung der meinen.

          Bei deiner steigt jeder nicht-auch-nur-halbwegs-perl-Profi wie ich leider voll aus :-(

          Schon der nicht-mehr-ganz-so-Perl-Anfänger kann in der Doku nachschlagen, was die einzelnen Teile bedeuten. Es mag zwar ein paar Minuten brauchen, bis Du diese RegExp verstehst, aber ein Geheimnis - oder auch nur kompliziert - ist sie nicht.

          Dazu müsste man erst mal wissen, was (.) matcht (Irgendein einzelnes Zeichen?)
          und was in $1 drinnenliegt (der gematchte Asudruck??)

          Beides erfährst Du erstens in perldoc perlre, und sind zweitens die Grundlagen im Umgang mit Regular Expressions. Ebenso wie die Bedeutung des Parameters /e.

          Übrigens, an welcher Ascii-Tabelle orientiert sich Perl, wenn man chr(xxx) aufruft?

          Es gibt nur eine ASCII-Tabelle. Das "S" steht für "Standard".

          Da sind ja die Zeichenbelegungen ziemlich unterschiedlich, zumindest bei den Sonderzeichen!

          Bei allen nicht-ASCII-Zeichen siehst Du die Belegung, wenn Du mal kurz

          for (128..255) {
            print $_, "\t", chr($_), "\n";
          }

          auf die Konsole ausgeben läßt.

          Cheatah

        2. Hi Bernhard!

          viel zu statisch, besser so in der Richtung:
          $string =~ s/(.)/chr(ord($1)-5)/eg;

          mag sein, aber verstehen, wenn man bei regexpr. das überhaupt sagen kann ;-) tut man cheatahs Version am ehesten!

          Der Unterschied ist, dass Christians Version von *jedem* Zeichen 5 abziehen kann, nicht nur vom A.

          Dazu müsste man erst mal wissen, was (.) matcht (Irgendein einzelnes Zeichen?)
          und was in $1 drinnenliegt (der gematchte Asudruck??)

          Da gebe ich Cheatah recht, das sind wirklich die elementaren Grundlagen der RegExpe, aber Dein Gefuehl hat Dich ja schon in die richtige Richtung gefuehrt. Bleibt noch zu erwaehnen, dass das e nach dem letzten / bedeutet, dass der Ersetzungsausdruck keine Zeichenkette ist, sondern als Perl-Statement ausgewertet wird. Aber das hats Du Dir sicher auch schon gedacht oder - noch besser - mittlerweile in perlre (diesmal ohne f *g*) gelesen. ;-)

          Übrigens, an welcher Ascii-Tabelle orientiert sich Perl, wenn man chr(xxx) aufruft? Da sind ja die Zeichenbelegungen ziemlich unterschiedlich, zumindest bei den Sonderzeichen! Gibts da einen Standardzeichensatz?

          An gar keiner. Letztlich sind im Computer nur Zahlen drin und keine Zeichen. Und auch nach der Umwandlung mit chr() steht im Speicher in Wirklichkeit eine Zahl (dieselbe wie vorher), nur Perl weiss jetzt, dass es diesen Skalar als Zeichen behandeln soll und nicht als Zahl. Erst bei einer Ausgabe auf dem Bildschirm wird die in genau diesem Moment aktive Zeichentabelle verwendet, um das zu der Zahl zugehoerige Zeichen herauszusuchen. Wenn die Bildschirmausgabe auf der Console erfolgt, wird eben der Font der Console verwendet, werden die Zeichen aber zu einem Browser geschickt, wird eben die auf dem Client-Rechner aktive Zeichentabelle verwendet (welche sich in HTML wiederum durch ein META-Tag beeinflussen laesst).

          (Tatsaechlich gibt es nur eine echte (US-)ASCII-Tabelle, die nur aus den Zeichen 0 bis 127 besteht. Alles was danach kommt, sind andere Zeichensaetze nach irgendeiner Norm, z.B. iso-8859-1.)

          So long

          1. Hallo Calocybe

            Da gebe ich Cheatah recht, das sind wirklich die elementaren
            Grundlagen der RegExp,

            Ja, gut, ich glaubs ja, tut mir leid so blöd gefragt zu haben, aber
            ich vermeide RegExpr so gut es geht, da wird mein armes kleines
            Köpfchen immer so beansprucht, wenn ich mir zusammenreimen muss, wie
            ich das hindrehen kann, dass man mit möglichst wenig wirr
            arrangierten Zeichen nach einem Wort suchen kann. Echt, da lauf ich
            immer heiss, vielleich denke ich ja zu kompliziert, aber ich krieg
            da nie den Ausdruck zustande, der genau das macht was ich will!

            aber Dein Gefuehl hat Dich ja schon in die richtige Richtung
            gefuehrt. Bleibt noch zu erwaehnen, dass das e nach dem letzten /
            bedeutet, dass der Ersetzungsausdruck keine Zeichenkette ist,
            sondern als Perl-Statement ausgewertet wird. Aber das hats Du Dir
            sicher auch schon gedacht oder - noch besser - mittlerweile in
            perlre (diesmal ohne f *g*) gelesen. ;-)

            Danke, dass du es mir dennoch erklärt hast! Und ich hätte da auch
            gleich mal nen Vorschlag: Du kennst doch sicher die "Glücksspirale"
            von SAT1 oder? Da können Leute, die vor irgendwas (z.B.: Spinnen,..)
            panische Angst haben, wenn sie ihre Furcht überwinden, tolle Preise
            gewinnen! -Dort könnte ich mich anmelden. Ich lese vor laufender
            Kamera das gesamte perldoc perlre durch, von oben bis unten, ohne
            Absetzen ;-) Und als Preis würde ich vorschlagen: einen Tag mit dem
            Genie das PERL "erfunden" hat zu verbringen, damit ich dann mein
            frisch erworbenes Wissen gleich an den Mann bringen kann. Der kann
            sicher stundenlang über Reguläre Ausdrücke schwafeln ! Na, und ich
            dann ja auch ;-)

            Oder ich zieh mich in eine einsame Hütte in irgendeinem abgelegenen
            Waldstück zurück, und zieh sie mir dort rein. Da kann mich keiner
            sehen, wenn ich mich meinem Leiden ergebe, und dem Wahnsinn näher
            als ein ganzes "Irrenhaus" von einer Ecke in die andere laufe und
            nur noch wirre Wörter stammle:
            "s...slash...backslash..s..nein..n..dann..oder.. oder nicht...oder
            und...nein t....blödsinn...slash...eckige klammer
            auf...dann....punkt..."

            jetzt muss ich sogar selbst ein wenig *grinsen*

            Erst bei einer Ausgabe auf dem Bildschirm wird die in genau
            diesem Moment aktive Zeichentabelle verwendet, um das zu der Zahl
            zugehoerige Zeichen herauszusuchen. Wenn die Bildschirmausgabe
            auf der Console erfolgt, wird eben der Font der Console
            verwendet, werden die Zeichen aber zu einem Browser geschickt,
            wird eben die auf dem Client-Rechner aktive Zeichentabelle
            verwendet (welche sich in HTML wiederum durch ein META-Tag
            beeinflussen laesst).

            Das war jetzt aufschlussreich, danke, ich glaube es hat gefruchtet!

            (Tatsaechlich gibt es nur eine echte (US-)ASCII-Tabelle, die nur
            aus den Zeichen 0 bis 127 besteht. Alles was danach kommt, sind
            andere Zeichensaetze nach irgendeiner Norm, z.B. iso-8859-1.)

            huch, und was passiert jetzt, ich spür so ein Kribbeln bei meinen
            Füssen, ich glaube ... ja ... oh ... es hat nicht nur gefruchtet,
            nein es schlägt auch schon Wurzeln ;-)

            Ich hab bloss in div. Büchern oft 10 oder mehr verschiedene Ascii-
            Tabellen gesehen, und daher hab ich mich auch schon immer gefragt,
            wozu das Ding eigentlich _Standard_ heisst, wenns doch erst wieder
            1000 verschiedene Versionen davon gibt! Naja, aber dass sich nur die
            Zeichen 128-255 unterscheiden, da bin ich wiedermal nicht
            dahintergestiegen, und gesagt hats mir auch keiner, bis zum heutigen
            Tage !

            So long

            so lang hats gar nicht gedauert oder ?

            liebe Grüsse
            Bernhard

    2. Hallo Cheatah,

      $string =~ s/A/chr(60)/eg;

      Das Problem ist, das ich nicht nur das A sondern jedes beliebige Zeichen herab oder herauf setzen muss!

      cu,
      Johannes

      1. Hi,

        $string =~ s/A/chr(60)/eg;
        Das Problem ist, das ich nicht nur das A sondern jedes beliebige Zeichen herab oder herauf setzen muss!

        immer gleich? Dann ist Christians Lösung vermutlich das, was Du suchst; auch wenn sie mit einigen Zeichen (< ASCII 5, > ASCII 250) Probleme haben könnte.

        Es ist aber nicht Sinn und Zwecke des _Self_HTML-Forums, Dir hier fertige Lösungen zu präsentieren. Ich habe Dir drei potentielle Kandidaten für Dein Problem genannt; den Rest mußt Du selbst machen. Wenn Du an einer Stelle auf spezifische Probleme stößt, helfen wir Dir gerne weiter.

        Cheatah

        1. Hi,

          auch wenn sie mit einigen Zeichen (< ASCII 5, > ASCII 250) Probleme haben könnte.

          Eigentlich hatte ich _absichtlich_ nicht auf das Problem hingewiesen, damit er selber darauf kommt und
          drüber nachdenkt.
          Zu lösen ist das jedoch recht einfach mit

          $string =~ s/(.)/chr((ord($1) > 250 ord($1) < 5) ? (ord($1) > 250 ?  (ord($1) - 250) : (ord($1) + 250)) : (ord($1) - 5))/eg;

          (Ich mag es, fies zu sein *gg*)

          mfg
          CK1

          1. Moin!

            $string =~ s/(.)/chr((ord($1) > 250 || ord($1) < 5) ? (ord($1) > 250 ?  (ord($1) - 250) : (ord($1) + 250)) : (ord($1) - 5))/eg;

            Mmh.. Du musst Dich schon entscheiden, ob Du nun 5 addieren oder subtrahieren willst. Fuer den Fall der Subtraktion schlage ich diese kleine Optimierung vor (untested):

            $string =~ s/(.)/chr((ord($1) + 256 - 5) & 0xFF)/eg;

            (Die Addition von 256 soll einen Unterlauf unter 0 vermeiden. Normalerweise sollte das nicht noetig sein, aber wer weiss, was auf irgendeiner exotischen Plattform alles passieren kann.)

            So long

            1. Hi,

              also erstmal: das Posting war nicht ganz ernst gemeint ;)

              $string =~ s/(.)/chr((ord($1) > 250 ord($1) < 5) ? (ord($1) > 250 ?  (ord($1) - 250) : (ord($1) + 250)) : (ord($1) - 5))/eg;

              Mmh.. Du musst Dich schon entscheiden, ob Du nun 5 addieren oder subtrahieren willst.

              hmpf, blöde Vorzeichenfehler... ich hab jetzt verquert gedacht, mit +5 und nicht -5 ;-)

              also kann der Fall doch noch weiter vereinfacht werden:
              $string =~ s/(.)/chr((ord($1) < 5) ? (ord($1) + 250)) : (ord($1) - 5))/eg;

              Schade, es war so schön kompliziert ;-D

              $string =~ s/(.)/chr((ord($1) + 256 - 5) & 0xFF)/eg;

              oder eben so ;)

              mfg
              CK1

        2. Hallo Cheatah,

          immer gleich? Dann ist Christians Lösung vermutlich das, was Du suchst; auch wenn sie mit einigen Zeichen (< ASCII 5, > ASCII 250) Probleme haben könnte.

          Nein, verschieden (z.B. in einer Schleife, um x wird immer dazugezählt und x wird am Ende jeder Schleife + 2 genommen!)

          Es ist aber nicht Sinn und Zwecke des _Self_HTML-Forums, Dir hier fertige Lösungen zu präsentieren. Ich habe Dir drei potentielle Kandidaten für Dein Problem genannt; den Rest mußt Du selbst machen. Wenn Du an einer Stelle auf spezifische Probleme stößt, helfen wir Dir gerne weiter.

          Nein, natürlich nicht. Jetzt da ich das mit dem chr() und ord() weiß (ist ja wie z.B. in Qbasic) weiß ich es eh ungefähr. Aber ich konnte in SelfHTML nichts finden und so dachte ich mir, vielleicht enthält Perl so eine Funktion nicht!

          cu,
          Johannes

          1. Hi,

            immer gleich?
            Nein, verschieden (z.B. in einer Schleife, um x wird immer dazugezählt und x wird am Ende jeder Schleife + 2 genommen!)

            (nebenbei: Bitte laß zwischen Zitat und eigenem Text eine Leerzeile; dann brauche ich nicht immer zu suchen, was denn jetzt eigentlich von Dir ist, danke!)

            Wenn ich das richtig verstehe, ist zu einem Zeitpunkt t die Verschiebung für alle Zeichen gleich. Dann läßt sich die in diesem Thread gennante Lösung entsprechend verallgemeinern: $x statt 5.

            Nein, natürlich nicht. Jetzt da ich das mit dem chr() und ord() weiß (ist ja wie z.B. in Qbasic) weiß ich es eh ungefähr. Aber ich konnte in SelfHTML nichts finden und so dachte ich mir, vielleicht enthält Perl so eine Funktion nicht!

            Ich habe schon mehrfach - zu Stefans Leidwesen[1] ;-) - zum Ausdruck gebracht, was ich vom Perl-Kapitel in SelfHTML halte: Es ist in etwa so schlecht, wie die anderen Kapitel gut sind. Also mies. Du solltest es tunlichst vergessen und statt dessen die bei Perl mitgelieferte Doku verwenden. Linksetzer hat ja bereits seinen Job getan ;-) und einen Link auf eine Online-Version gesetzt; wenn Du Perl bei Dir installiert hast, bekommst Du aber das gleiche, indem Du auf Deinem System

            perldoc perlfunc

            eingibst. Mit

            perldoc -f chr

            bekommst Du dann beispielsweise die Doku zum Befehl chr.

            Cheatah

            [1] Ist aber nicht böse gemeint, Stefan, ich hoffe Du weißt das!