Escape-Sequenzen in Python-Strings          (C) 2016-2021 T.Birnthaler OSTC GmbH
==================================

Doku --> docs.python.org/3/reference/lexical_analysis.html#literals
         docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals

Das Zeichen "\" (Backslash) dient in Python innerhalb von Strings als
Escape-Zeichen ("Fluchtzeichen"), das zusammen mit dem DIREKT FOLGENDEN Zeichen
eine spezielle Bedeutung hat. Darüber werden z.B. Steuerzeichen (Strg-Z) und
Unicode-Zeichen über ihre CODIERUNG oder ihren NAMEN angesprochen.

Folgende Kombinationen sind möglich:

  +------------+----------------------------------------------------------+
  | Zeichen    | Bedeutung                                                |
  +------------+----------------------------------------------------------+
  | \\         | Backslash selbst (immer verdoppeln!)         [backslash] |
  | \'         | Hochkomma (in '...' notwendig)            [single quote] |
  | \"         | Gänsefüßchen (in "..." notwendig)         [double quote] |
  +------------+----------------------------------------------------------+
  | \a         | Klingel (BEL)                                    [alert] |
  | \b         | Rückschritt (BS)                             [backspace] |
  | \e         | Escape (ESC)                                    [escape] |
  | \f         | Seitenvorschub (FF)                          [form feed] |
  | \n         | Zeilenumbruch (LF)                   [newline, linefeed] |
  | \r         | Wagenrücklauf (CR)                     [carriage return] |
  | \t         | Horizontaler Tabulator (HT)                  [tabulator] |
  | \v         | Vertikaler Tabulator (VT)           [vertical tabulator] |
  +------------+----------------------------------------------------------+
  | \0         | Null-Byte (NUL)                                   [null] |
  | \OOO       | Zeichen mit Oktalcode "OOO" (000-377)            [octal] |
  | \xHH       | Zeichen mit Hexadezimalcode "HH" (00-ff)   [hexadezimal] |
  | \N{NAME}   | Zeichen mit Unicode-Name "NAME"                   [Name] |
  | \uXXXX     | Zeichen mit 16-bit Unicode-Wert "XXXX"         [unicode] |
  | \UXXXXXXXX | Zeichen mit 32-bit Unicode-Wert "XXXXXXXX"     [Unicode] |
  +------------+----------------------------------------------------------+
  | \<NEWLINE> | Zeilenende wird ignoriert            [line continuation] |
  | \<SONST>   | Bleibt stehen inkl. Backslash                  [FEHLER]  |
  +------------+----------------------------------------------------------+

HINWEISE:

* Innerhalb von RAW-STRINGS r"..." oder R"..." werden Escape-Sequenzen
  nicht interpretiert, der Backslash zählt als normales Zeichen.

* Ein Backslash am Zeilenende ("Line Continuation") verknüpft die aktuelle
  Zeile mit der folgenden zu einer LOGISCHEN ZEILE und erlaubt so eine
  beliebige Unterteilung von langen Zeilen in kurze Stücke. Die Einrückung der
  Folgezeile ist dabei irrelevant und muss nicht den Einrückungsregeln von
  Python gehorchen.

    erg = 1 + \2 + \3

* Zeichenketten werden durch folgende Syntax definiert (quotiert):

  +-----------------+-----+-------------------------------------------------+
  | Syntax          |     | Bedeutung                                       |
  +-----------------+-----+-------------------------------------------------+
  | "..."           | E 1 | Alle Zeichen (außer " und Zeilenvorschub)       |
  | '...'           | E 1 | Alle Zeichen (außer ' und Zeilenvorschub)       |
  | """..."""       | E m | Alle Zeichen (inklusive " ' und Zeilenvorschub) |
  | '''...'''       | E m | Alle Zeichen (inklusive " ' und Zeilenvorschub) |
  +-----------------+-----+-------------------------------------------------+
  | b"..."  B"..."  | E 1 | Binär-String (STD in P2)                        |
  | f"..."  F"..."  | E 1 | Format-String mit Platzhaltern der Form {...}   |
  | r"..."  R"..."  | - 1 | Raw-String (Escape-Sequenz nicht interpretiert) |
  | u"..."  U"..."  | E 1 | Unicode-String (STD in P3)                      |
  +-----------------+-----+-------------------------------------------------+
  | ur"..." UR"..." | - 1 | Raw-String im Unicode-Format                    |
  | ru"..." RU"..." | - 1 | Raw-String im Unicode-Format                    |
  | fr"..." FR"..." | - 1 | Raw-Format-String                               |
  | rf"..." RF"..." | - 1 | Raw-Format-String                               |
  | br"..." BR"..." | - 1 | Raw-Binär-String                                |
  | rb"..." RB"..." | - 1 | Raw-Binär-String                                |
  +-----------------+-----+-------------------------------------------------+
    E = Escape-Sequenz \X wird interpretiert
    - = Escape-Sequenz \X bleibt stehen (2 Zeichen)
    1 = Nur einzeiliger String möglich
    m = Mehrzeiliger String sowie ' und " im String erlaubt

HINWEIS:

* String-Literale, die DIREKT aufeinander folgen, werden automatisch verkettet
  (das Verkettungszeichen "+" dazwischen ist nicht notwendig):

    "hallo" "welt" 'usw.'            # --> 'halloweltusw.'
    "hallo" + "welt" + 'usw.'        # --> 'halloweltusw.'
    "hallo" ' ' "welt" ' ' "usw."    # --> 'hallo welt usw.'

  Gilt auch dann, wenn die String-Literale auf mehrere Zeilen verteilt sind:

    "hallo"                          # --> "halloweltusw."
    "welt"                           #
    "usw."                           #

  Funktioniert allerdings NICHT mit Variablen, Funktionen, Konstanten, ...

    text                             # text = "hallo"
    "welt".upper()                   # Funktion auf String "welt" anwenden
    string.ascii_lowercase           # Konstante

BEISPIELE:

  print("Hallll\b\bo\t\\Welt")       # 'Hallo    \Welt'
  print('Hallll\b\bo\t\\Welt')       # 'Hallo    \Welt'
  print('''Hallll\b\bo\t\\Welt''')   # 'Hallo    \Welt'
  print("""Hallll\b\bo\t\\Welt""")   # 'Hallo    \Welt'
  print(r"Hallll\b\bo\t\\Welt")      # 'Hallll\b\bo\t\\Welt'    raw-String
  print(R"Hallll\b\bo\t\\Welt")      # 'Hallll\b\bo\t\\Welt'    raw-String
  print("Hallo \                     # Zeilenfortsetzung im String
         Welt")                      # (\n unterdrückt, Präfix 2. Zeile dabei)
  print("Hallo " + \                 # Zeilenfortsetzung im Code
        "Welt")                      # (\n und Präfix 2. Zeile unterdrückt)
  print("Hallo " "Welt")             # 'Hallo Welt' (automatische Verkettung)
  print("Hallo " + "Welt")           # 'Hallo Welt' (explizite Verkettung)

Unicode-Zeichen per Code und per Name ansprechen:

  print(
      "\x41 \101 \u0041 \U00000041 \N{LATIN CAPITAL LETTER A}",         # A A A
      "\x61 \141 \u0061 \U00000061 \N{LATIN SMALL LETTER A}",           # a a a
      "\u03C0 \U000003C0 \N{GREEK SMALL LETTER PI}",                    # π π π
      "\u03A0 \U000003A0 \N{GREEK CAPITAL LETTER PI}",                  # Π Π Π
      "\u00E4 \U000000E4 \N{LATIN SMALL LETTER A WITH DIAERESIS}",      # ä ä ä
      "\u00F6 \U000000F6 \N{LATIN SMALL LETTER O WITH DIAERESIS}",      # ö ö ö
      "\u00FC \U000000FC \N{LATIN SMALL LETTER U WITH DIAERESIS}",      # ü ü ü
      "\u00DF \U000000DF \N{LATIN SMALL LETTER SHARP S}",               # ß ß ß
      "\u00C4 \U000000C4 \N{LATIN CAPITAL LETTER A WITH DIAERESIS}",    # Ä Ä Ä
      "\u00D6 \U000000D6 \N{LATIN CAPITAL LETTER O WITH DIAERESIS}",    # Ö Ö Ö
      "\u00DC \U000000DC \N{LATIN CAPITAL LETTER U WITH DIAERESIS}",    # Ü Ü Ü
      "\u00D7 \U000000D7 \N{MULTIPLICATION SIGN}",                      # × × ×
      "\u4e14 \U00004e14 \N{CJK UNIFIED IDEOGRAPH-4E14}",               # 且 且 且
      sep="\n",
  )

HINWEIS: Bei Thonny gibt es leider Schwierigkeiten mit Unicode-Zeichen
         ab "\U0010000", diese führen zum "Einfrieren" der GUI.

      "\U0001f970 \N{SMILING FACE WITH SMILING EYES AND THREE HEARTS}", # 🥰 🥰 🥰

Konvertierungs-Funktionen:

  print(
    hex(ord('π')),                # '03c0' (hexadecimal, ordinal)
    hex(ord('\u03C0')),           # '03c0'
    ord('π'),                     # 960
    ord('\u03C0'),                # 960
    chr(0x03C0),                  # 'π'    (character)
    chr(960),                     # 'π'
    chr(int('03C0', 16)),         # 'π'
    chr(int('0x03C0', 0)),        # 'π'
    sep="\n",
  )

  import unicodedata            # Modul importieren
  print(
    unicodedata.name('\u03A0'),    # 'GREEK CAPITAL LETTER PI'
    unicodedata.name('\u03C0'),    # 'GREEK SMALL LETTER PI'
    sep="\n",
  )