MÖGLICHE LÖSUNG
Daher habe ich die folgenden Informationen zusammengestellt:
for class in $(
locale -v LC_CTYPE |
sed 's/combin.*//;s/;/\n/g;q'
) ; do
printf "\n\t%s\n\n" $class
recode u2/test16 -q </dev/null |
tr -dc "[:$class:]" |
od -A n -t a -t o1z -w12
done
HINWEIS :
Ich benutze od
als letzten Filter oben und weil ich weiß, dass ich nicht mit Multi-Byte-Zeichen arbeiten werde, die es nicht richtig handhaben wird. recode u2..dump
Beide erzeugen eine Ausgabe, die der in der Frage angegebenen ähnelt, und verarbeiten breite Zeichen korrekt.
AUSGABE
upper
A B C D E F G H I J K L
101 102 103 104 105 106 107 110 111 112 113 114 >ABCDEFGHIJKL<
M N O P Q R S T U V W X
115 116 117 120 121 122 123 124 125 126 127 130 >MNOPQRSTUVWX<
Y Z
131 132 >YZ<
lower
a b c d e f g h i j k l
141 142 143 144 145 146 147 150 151 152 153 154 >abcdefghijkl<
m n o p q r s t u v w x
155 156 157 160 161 162 163 164 165 166 167 170 >mnopqrstuvwx<
y z
171 172 >yz<
alpha
A B C D E F G H I J K L
101 102 103 104 105 106 107 110 111 112 113 114 >ABCDEFGHIJKL<
M N O P Q R S T U V W X
115 116 117 120 121 122 123 124 125 126 127 130 >MNOPQRSTUVWX<
Y Z a b c d e f g h i j
131 132 141 142 143 144 145 146 147 150 151 152 >YZabcdefghij<
k l m n o p q r s t u v
153 154 155 156 157 160 161 162 163 164 165 166 >klmnopqrstuv<
w x y z
167 170 171 172 >wxyz<
digit
0 1 2 3 4 5 6 7 8 9
060 061 062 063 064 065 066 067 070 071 >0123456789<
xdigit
0 1 2 3 4 5 6 7 8 9 A B
060 061 062 063 064 065 066 067 070 071 101 102 >0123456789AB<
C D E F a b c d e f
103 104 105 106 141 142 143 144 145 146 >CDEFabcdef<
space
ht nl vt ff cr sp
011 012 013 014 015 040 >..... <
print
sp ! " # $ % & ' ( ) * +
040 041 042 043 044 045 046 047 050 051 052 053 > !"#$%&'()*+<
, - . / 0 1 2 3 4 5 6 7
054 055 056 057 060 061 062 063 064 065 066 067 >,-./01234567<
8 9 : ; < = > ? @ A B C
070 071 072 073 074 075 076 077 100 101 102 103 >89:;<=>?@ABC<
D E F G H I J K L M N O
104 105 106 107 110 111 112 113 114 115 116 117 >DEFGHIJKLMNO<
P Q R S T U V W X Y Z [
120 121 122 123 124 125 126 127 130 131 132 133 >PQRSTUVWXYZ[<
\ ] ^ _ ` a b c d e f g
134 135 136 137 140 141 142 143 144 145 146 147 >\]^_`abcdefg<
h i j k l m n o p q r s
150 151 152 153 154 155 156 157 160 161 162 163 >hijklmnopqrs<
t u v w x y z { | } ~
164 165 166 167 170 171 172 173 174 175 176 >tuvwxyz{|}~<
graph
! " # $ % & ' ( ) * + ,
041 042 043 044 045 046 047 050 051 052 053 054 >!"#$%&'()*+,<
- . / 0 1 2 3 4 5 6 7 8
055 056 057 060 061 062 063 064 065 066 067 070 >-./012345678<
9 : ; < = > ? @ A B C D
071 072 073 074 075 076 077 100 101 102 103 104 >9:;<=>?@ABCD<
E F G H I J K L M N O P
105 106 107 110 111 112 113 114 115 116 117 120 >EFGHIJKLMNOP<
Q R S T U V W X Y Z [ \
121 122 123 124 125 126 127 130 131 132 133 134 >QRSTUVWXYZ[\<
] ^ _ ` a b c d e f g h
135 136 137 140 141 142 143 144 145 146 147 150 >]^_`abcdefgh<
i j k l m n o p q r s t
151 152 153 154 155 156 157 160 161 162 163 164 >ijklmnopqrst<
u v w x y z { | } ~
165 166 167 170 171 172 173 174 175 176 >uvwxyz{|}~<
blank
ht sp
011 040 >. <
cntrl
nul soh stx etx eot enq ack bel bs ht nl vt
000 001 002 003 004 005 006 007 010 011 012 013 >............<
ff cr so si dle dc1 dc2 dc3 dc4 nak syn etb
014 015 016 017 020 021 022 023 024 025 026 027 >............<
can em sub esc fs gs rs us del
030 031 032 033 034 035 036 037 177 >.........<
punct
! " # $ % & ' ( ) * + ,
041 042 043 044 045 046 047 050 051 052 053 054 >!"#$%&'()*+,<
- . / : ; < = > ? @ [ \
055 056 057 072 073 074 075 076 077 100 133 134 >-./:;<=>?@[\<
] ^ _ ` { | } ~
135 136 137 140 173 174 175 176 >]^_`{|}~<
alnum
0 1 2 3 4 5 6 7 8 9 A B
060 061 062 063 064 065 066 067 070 071 101 102 >0123456789AB<
C D E F G H I J K L M N
103 104 105 106 107 110 111 112 113 114 115 116 >CDEFGHIJKLMN<
O P Q R S T U V W X Y Z
117 120 121 122 123 124 125 126 127 130 131 132 >OPQRSTUVWXYZ<
a b c d e f g h i j k l
141 142 143 144 145 146 147 150 151 152 153 154 >abcdefghijkl<
m n o p q r s t u v w x
155 156 157 160 161 162 163 164 165 166 167 170 >mnopqrstuvwx<
y z
PROGRAMMER'S API
Wie ich unten demonstriere, recode
bekommst du deine komplette Charakterkarte. Entsprechend dem Handbuch wird dies zuerst anhand des aktuellen Werts der DEFAULT_CHARSET
Umgebungsvariablen ausgeführt. Andernfalls wird genau so vorgegangen, wie Sie es angegeben haben:
Wenn ein Zeichensatzname weggelassen oder leer gelassen DEFAULT_CHARSET
wird, wird stattdessen der Wert der Variablen in der Umgebung verwendet. Wenn diese Variable nicht definiert ist, verwendet die recode
Bibliothek die Codierung des aktuellen Gebietsschemas. Bei POSIX- kompatiblen Systemen hängt dies vom ersten nicht leeren Wert unter den Umgebungsvariablen ab LC_ALL, LC_CTYPE, LANG
und kann über den Befehl ermittelt werdenlocale charmap.
Erwähnenswert recode
ist auch, dass es sich um eine API handelt :
Das genannte Programm recode
ist nur eine Anwendung seiner Rekodierungsbibliothek. Die Rekodierungsbibliothek ist für andere C-Programme separat erhältlich. Eine gute Möglichkeit, sich mit der Neukodierungsbibliothek vertraut zu machen, besteht darin, sich mit dem recode
Programm selbst vertraut zu machen .
Um die nach der Installation installierte Rekodierungsbibliothek zu verwenden, muss ein C-Programm eine Zeile haben:
#include <recode.h>
Für einen international freundlichen Stringvergleich definieren Die POSIX
und C
Standards die strcoll()
Funktion:
Die strcoll()
Funktion vergleicht die Zeichenfolge, auf die von verwiesen wird, mit s1
der Zeichenfolge, auf die von verwiesen wird s2
. Beide werden entsprechend der Kategorie LC_COLLATE des aktuellen Gebietsschemas interpretiert.
Die strcoll()
Funktion soll bei Erfolg die Einstellung von errno nicht ändern.
Da kein Rückgabewert reserviert ist, um einen Fehler anzuzeigen, sollte eine Anwendung, die nach Fehlersituationen suchen möchte, errno auf 0 setzen, dann aufrufen
strcoll()
und dann errno überprüfen.
Hier ist ein separat platziertes Beispiel für die Verwendung:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abc");
strcpy(str2, "ABC");
ret = strcoll(str1, str2);
if(ret > 0)
{
printf("str1 is less than str2");
}
else if(ret < 0)
{
printf("str2 is less than str1");
}
else
{
printf("str1 is equal to str2");
}
return(0);
}
In Bezug auf die POSIX
Zeichenklassen haben Sie bereits festgestellt, dass Sie die C
API verwendet haben, um diese zu finden. Für Unicode-Zeichen und -Klassen können Sie den Zeichensatz recode's
dump-with-names verwenden , um die gewünschte Ausgabe zu erhalten. Nochmals aus dem Handbuch :
Beispielsweise recode l2..full < input
impliziert der Befehl eine notwendige Konvertierung von Latin-2 nach UCS-2, da dump-with-names nur von UCS-2 aus verbunden wird. In solchen Fällen werden im Dump recode
nicht die ursprünglichen Latin-2- Codes angezeigt , sondern
nur die entsprechenden UCS-2- Werte. Um ein einfaches Beispiel zu geben, der Befehl
echo 'Hello, world!' | recode us..dump
erzeugt die folgende Ausgabe:
UCS2 Mne Description
0048 H latin capital letter h
0065 e latin small letter e
006C l latin small letter l
006C l latin small letter l
006F o latin small letter o
002C , comma
0020 SP space
0077 w latin small letter w
006F o latin small letter o
0072 r latin small letter r
006C l latin small letter l
0064 d latin small letter d
0021 ! exclamation mark
000A LF line feed (lf)
Der beschreibende Kommentar ist in Englisch und ASCII angegeben. Wenn jedoch keine englische, sondern eine französische Beschreibung verfügbar ist, wird stattdessen die französische Beschreibung mit Latin-1 angegeben. Wenn jedoch die
Umgebungsvariable LANGUAGE
oder LANG
mit den Buchstaben fr beginnt , wird die Listeneinstellung auf Französisch gesetzt, wenn beide Beschreibungen verfügbar sind.
Wenn ich eine ähnliche Syntax wie oben in Kombination mit dem enthaltenen Testdatensatz verwende, kann ich meine eigene Zeichentabelle erstellen mit:
recode -q u8/test8..dump </dev/null
AUSGABE
UCS2 Mne Description
0001 SH start of heading (soh)
0002 SX start of text (stx)
0003 EX end of text (etx)
...
002B + plus sign
002C , comma
002D - hyphen-minus
...
0043 C latin capital letter c
0044 D latin capital letter d
0045 E latin capital letter e
...
006B k latin small letter k
006C l latin small letter l
006D m latin small letter m
...
007B (! left curly bracket
007C !! vertical line
007D !) right curly bracket
007E '? tilde
007F DT delete (del)
Aber für gewöhnliche Charaktere recode
ist das anscheinend nicht nötig. Dies sollte Ihnen benannte Zeichen für alles im 128-Byte-Zeichensatz geben:
printf %b "$(printf \\%04o $(seq 128))" |
luit -c |
od -A n -t o1z -t a -w12
AUSGABE
001 002 003 004 005 006 007 010 011 012 013 014 >............<
soh stx etx eot enq ack bel bs ht nl vt ff
...
171 172 173 174 175 176 177 >yz{|}~.<
y z { | } ~ del
Natürlich werden nur 128 Bytes dargestellt, aber das liegt daran, dass mein Gebietsschema, utf-8 charmaps oder nicht, den ASCII- Zeichensatz verwendet und sonst nichts. Das ist alles was ich bekomme. Wenn ich es luit
laufen lassen od
würde, ohne es zu filtern, würde ich es zurückrollen und die gleiche Karte erneut drucken, bis\0400.
Es gibt jedoch zwei Hauptprobleme bei der obigen Methode. Erstens gibt es die Sortierreihenfolge des Systems - für Nicht-ASCII-Gebietsschemata sind die Bite-Werte für die Zeichensätze nicht einfach von seq
Bedeutung, was, wie ich denke, der Kern des Problems ist, das Sie zu lösen versuchen.
Nun, auf der GNU- tr's man
Seite heißt es, dass die [:upper:]
[:lower:]
Klassen der Reihe nach erweitert werden - aber das ist nicht viel.
Ich stelle mir vor sort
, dass eine schwierige Lösung implementiert werden könnte, aber das wäre ein ziemlich unhandliches Werkzeug für eine Backend-Programmierschnittstelle.
recode
Ich werde das richtig machen, aber Sie schienen neulich nicht allzu verliebt in das Programm zu sein. Vielleicht werden die heutigen Änderungen ein freundlicheres Licht darauf werfen oder vielleicht auch nicht.
GNU bietet auch die gettext
Funktionsbibliothek an, und es scheint in der Lage zu sein , dieses Problem zumindest für den LC_MESSAGES
Kontext anzugehen :
- Funktion: char * bind_textdomain_codeset
( const char *domainname,
const char *codeset
)
Die bind_textdomain_codeset
Funktion kann verwendet werden , um das Ausgangszeichensatz für die Nachrichtenkataloge für Domäne angeben
domänen . Das Argument codeset muss ein gültiger Codename sein, der für die Funktion iconv_open verwendet werden kann, oder ein Nullzeiger.
Wenn der Codeset- Parameter der Nullzeiger ist, wird bind_textdomain_codeset
der aktuell ausgewählte Codeset für die Domäne mit dem Namen
Domänenname zurückgegeben . Es wird NULL zurückgegeben, wenn noch kein Codesatz ausgewählt wurde.
Die bind_textdomain_codeset
Funktion kann mehrmals verwendet werden. Bei mehrmaliger Verwendung mit demselben Domainnamen-Argument überschreibt der spätere Aufruf die Einstellungen des früheren.
Die bind_textdomain_codeset
Funktion gibt einen Zeiger auf eine Zeichenfolge zurück, die den Namen des ausgewählten Codesatzes enthält. Der String wird funktionsintern vergeben und darf vom Benutzer nicht verändert werden. Wenn das System während der Ausführung von bind_textdomain_codeset
den Core verlassen hat
, ist der Rückgabewert NULL und die globale Variable errno wird entsprechend gesetzt.
Sie könnten auch die native verwenden Unicode - Zeichenkategorien , die sprachunabhängig sind und die POSIX - Klassen ganz verzichten, oder vielleicht auf dem ehemaligen rufen Sie genügend Informationen , um die letztere zu definieren.
Neben Komplikationen bringt Unicode auch neue Möglichkeiten. Zum einen gehört jedes Unicode-Zeichen zu einer bestimmten Kategorie. Sie können ein einzelnes Zeichen der Kategorie "Buchstabe" mit zuordnen
\p{L}
. Sie können ein einzelnes Zeichen, das nicht zu dieser Kategorie gehört, mit abgleichen \P{L}
.
Auch hier bedeutet "Zeichen" "Unicode-Codepunkt". \p{L}
Entspricht einem einzelnen Codepunkt in der Kategorie "Buchstabe". Wenn Ihre Eingabezeichenfolge als à
codiert ist U+0061 U+0300
, stimmt sie a
ohne den Akzent überein . Wenn die Eingabe als à
codiert ist U+00E0
, stimmt sie à
mit dem Akzent überein . Der Grund ist, dass sowohl die Codepunkte U+0061 (a)
als U+00E0 (à)
auch in der Kategorie "Buchstabe" sind, während sie U+0300
in der Kategorie "Marke" sind.
Sie sollten jetzt verstehen, warum \P{M}\p{M}*+
das Äquivalent von ist \X
.
\P{M}
Stimmt mit einem Codepunkt überein, der keine Kombinationsmarke ist, während \p{M}*+
null oder mehr Codepunkte übereinstimmen, die Marken kombinieren. Verwenden Sie, um einen Buchstaben mit diakritischen Zeichen abzugleichen \p{L}\p{M}*+
. Dieser letzte reguläre Ausdruck stimmt immer überein à
, unabhängig davon, wie er codiert ist. Der Possessive Quantifier stellt sicher, dass das Backtracking nicht dazu führt, dass \P{M}\p{M}*+
eine Nicht-Marke ohne die darauf folgenden Kombinationsmarken abgeglichen wird, was \X
niemals der Fall wäre.
Auf derselben Website, auf der die oben genannten Informationen bereitgestellt wurden, wird auch die Tcl
eigene POSIX- konforme Regex-Implementierung erläutert , die möglicherweise ein weiterer Weg ist, Ihr Ziel zu erreichen.
Und als letztes unter den Lösungen schlage ich vor, dass Sie die LC_COLLATE
Datei selbst nach der vollständigen und in der Reihenfolge angeordneten Systemzeichentabelle abfragen können . Dies scheint nicht einfach zu sein, aber ich habe einige Erfolge erzielt, nachdem ich es localedef
wie folgt kompiliert habe :
<LC_COLLATE od -j2K -a -w2048 -v |
tail -n2 |
cut -d' ' -f$(seq -s',' 4 2 2048) |
sed 's/nul\|\\0//g;s/ */ /g;:s;
s/\([^ ]\{1,3\}\) \1/\1/;ts;
s/\(\([^ ][^ ]* *\)\{16\}\)/\1\n/g'
dc1 dc2 dc3 dc4 nak syn etb can c fs c rs c sp ! "
# $ % & ' ( ) * + , - . / 0 1 2
3 4 5 6 7 8 9 : ; < = > ? @ A B
C D E F G H I J K L M N O P Q R
S T U V W X Y Z [ \ ] ^ _ ` a b
c d e f g h i j k l m n o p q r
s t u v w x y z { | } ~ del soh stx etx
eot enq ack bel c ht c vt cr c si dle dc1 del
Es ist zwar derzeit fehlerhaft, aber ich hoffe, es zeigt zumindest die Möglichkeit.
AUF DEN ERSTEN BLUSH
strings $_/en_GB
#OUTPUT
int_select "<U0030><U0030>"
...
END LC_TELEPHONE
Es sah wirklich nicht nach viel aus, aber dann bemerkte ich die copy
Befehle in der Liste. Die obige Datei scheint zum Beispiel copy
in "en_US" zu sein, und eine andere wirklich große Datei , die sie alle zu einem gewissen Grad zu teilen scheinen, ist iso_14651_t1_common
.
Es ist ziemlich groß:
strings $_ | wc -c
#OUTPUT
431545
Hier ist das Intro zu /usr/share/i18n/locales/POSIX
:
# Territory:
# Revision: 1.1
# Date: 1997-03-15
# Application: general
# Users: general
# Repertoiremap: POSIX
# Charset: ISO646:1993
# Distribution and use is free, also for
# commercial purposes.
LC_CTYPE
# The following is the POSIX Locale LC_CTYPE.
# "alpha" is by default "upper" and "lower"
# "alnum" is by definiton "alpha" and "digit"
# "print" is by default "alnum", "punct" and the <U0020> character
# "graph" is by default "alnum" and "punct"
upper <U0041>;<U0042>;<U0043>;<U0044>;<U0045>;<U0046>;<U0047>;<U0048>;\
<U0049>;<U004A>;<U004B>;<U004C>;<U004D>;<U004E>;<U004F>;
...
Sie können grep
dies natürlich durchmachen, aber Sie könnten einfach:
recode -lf gb
Stattdessen. Sie würden so etwas bekommen:
Dec Oct Hex UCS2 Mne BS_4730
0 000 00 0000 NU null (nul)
1 001 01 0001 SH start of heading (soh)
...
... UND MEHR
Es gibt auch ein luit
UTF-8- pty
Übersetzungsgerät für Endgeräte, das für XTerms ohne UTF-8-Unterstützung als Vermittler fungiert. Es verarbeitet eine Vielzahl von Schaltern - z. B. das Protokollieren aller konvertierten Bytes in einer Datei oder -c
als einfacher |pipe
Filter.
Ich habe nie bemerkt, dass es so viel zu diesem Thema gibt - die Locales und Charakterkarten und all das. Dies ist anscheinend eine sehr große Sache, aber ich denke, dass alles hinter den Kulissen weitergeht. Zumindest auf meinem System gibt es ein paar hundert man 3
ähnliche Ergebnisse für die Suche nach Gebietsschemas.
Und auch da ist:
zcat /usr/share/i18n/charmaps/UTF-8*gz | less
CHARMAP
<U0000> /x00 NULL
<U0001> /x01 START OF HEADING
<U0002> /x02 START OF TEXT
<U0003> /x03 END OF TEXT
<U0004> /x04 END OF TRANSMISSION
<U0005> /x05 ENQUIRY
...
Das wird noch sehr lange dauern.
Die Xlib
Funktionen erledigen dies die ganze Zeit - dies luit
ist ein Teil dieses Pakets.
Die Tcl_uni...
Funktionen könnten sich ebenfalls als nützlich erweisen.
nur ein wenig <tab>
vervollständigen und man
suchen und ich habe ziemlich viel zu diesem Thema gelernt.
Mit localedef
- können Sie die locales
in Ihrem I18N
Verzeichnis zusammenstellen. Die Ausgabe ist flippig und nicht außerordentlich nützlich - überhaupt nicht wie die charmaps
- aber Sie können das Rohformat so wie oben angegeben erhalten, wie ich es getan habe:
mkdir -p dir && cd $_ ; localedef -f UTF-8 -i en_GB ./
ls -l
total 1508
drwxr-xr-x 1 mikeserv mikeserv 30 May 6 18:35 LC_MESSAGES
-rw-r--r-- 1 mikeserv mikeserv 146 May 6 18:35 LC_ADDRESS
-rw-r--r-- 1 mikeserv mikeserv 1243766 May 6 18:35 LC_COLLATE
-rw-r--r-- 1 mikeserv mikeserv 256420 May 6 18:35 LC_CTYPE
-rw-r--r-- 1 mikeserv mikeserv 376 May 6 18:35 LC_IDENTIFICATION
-rw-r--r-- 1 mikeserv mikeserv 23 May 6 18:35 LC_MEASUREMENT
-rw-r--r-- 1 mikeserv mikeserv 290 May 6 18:35 LC_MONETARY
-rw-r--r-- 1 mikeserv mikeserv 77 May 6 18:35 LC_NAME
-rw-r--r-- 1 mikeserv mikeserv 54 May 6 18:35 LC_NUMERIC
-rw-r--r-- 1 mikeserv mikeserv 34 May 6 18:35 LC_PAPER
-rw-r--r-- 1 mikeserv mikeserv 56 May 6 18:35 LC_TELEPHONE
-rw-r--r-- 1 mikeserv mikeserv 2470 May 6 18:35 LC_TIME
Dann od
können Sie es mit lesen - Bytes und Strings:
od -An -a -t u1z -w12 LC_COLLATE | less
etb dle enq sp dc3 nul nul nul T nul nul nul
23 16 5 32 19 0 0 0 84 0 0 0 >... ....T...<
...
Obwohl es noch ein langer Weg ist, einen Schönheitswettbewerb zu gewinnen, ist dies eine brauchbare Ausgabe. Und od
ist natürlich so konfigurierbar, wie Sie es möchten.
Ich denke, ich habe auch diese vergessen:
perl -mLocale
-- Perl module --
Locale::Codes Locale::Codes::LangFam Locale::Codes::Script_Retired
Locale::Codes::Constants Locale::Codes::LangFam_Codes Locale::Country
Locale::Codes::Country Locale::Codes::LangFam_Retired Locale::Currency
Locale::Codes::Country_Codes Locale::Codes::LangVar Locale::Language
Locale::Codes::Country_Retired Locale::Codes::LangVar_Codes Locale::Maketext
Locale::Codes::Currency Locale::Codes::LangVar_Retired Locale::Maketext::Guts
Locale::Codes::Currency_Codes Locale::Codes::Language Locale::Maketext::GutsLoader
Locale::Codes::Currency_Retired Locale::Codes::Language_Codes Locale::Maketext::Simple
Locale::Codes::LangExt Locale::Codes::Language_Retired Locale::Script
Locale::Codes::LangExt_Codes Locale::Codes::Script Locale::gettext
Locale::Codes::LangExt_Retired Locale::Codes::Script_Codes locale
Ich habe sie wahrscheinlich vergessen, weil ich sie nicht zur Arbeit bringen konnte. Ich benutze es nie Perl
und ich weiß nicht, wie ich ein Modul richtig laden soll. Aber die man
Seiten sehen ziemlich gut aus. In jedem Fall sagt mir etwas, dass es für Sie weniger schwierig ist, ein Perl-Modul aufzurufen als ich. Und auch diese befanden sich bereits auf meinem Computer - und ich verwende niemals Perl. Es gibt auch einige I18N
, bei denen ich wehmütig gescrollt habe, weil ich wusste, dass ich sie auch nicht zum Arbeiten bringen würde.
/usr/share/i18n/locales/i18n
... die natürlich größtenteils aus der Unicode- Zeichendatenbank stammen. Natürlich wäre es schön, ein Kommando zu haben