Ich weiß, dass der cut
Befehl die ersten n
Zeichen einer Zeichenfolge drucken kann, aber wie wählt man die letzten n
Zeichen aus?
Wenn ich eine Zeichenfolge mit einer variablen Anzahl von Zeichen habe, wie kann ich nur die letzten drei Zeichen der Zeichenfolge drucken. z.B.
"Unbegrenzte" Ausgabe erforderlich ist "Ted" "987654" Ausgang benötigt wird "654" "123456789" benötigt die Ausgabe "789"
text-processing
cut
Odyssee
quelle
quelle
grep -o '.\{3\}$'
echo "unlimited" | python -c "print raw_input()[-3:]"
"echo unlimited" | java -jar EnterpriseWordTrimmer.jar
, aber ich denke nicht, dass es wirklich notwendig ist, eine schwerere Sprache für die Manipulation von Charakteren einzuführen.java -server -Xms300M -Xmx3G -XX:+UseParallelGC -cp /path/to/all/the/jars/ -Dinput.interactive=false -Dinput.pipe=true -Dconfig.file=/path/to/config/last-three-letters.cfg -jar ...
grep -o -P '.{0,3}$'
Gibt die letzten 3 Zeichen aus, auch wenn die Zeile weniger als 3 Zeichen enthält.-P
vermeidet es, den Zahnspangen zu entkommen.Halte es einfach - Schwanz
Wir sollten keinen regulären Ausdruck oder mehr als einen Prozess benötigen, nur um Zeichen zu zählen.
Der Befehl
tail
, der häufig zum Anzeigen der letzten Zeilen einer Datei verwendet wird, verfügt über eine option-c
(--bytes
), die genau das richtige Werkzeug dafür zu sein scheint:(Wenn Sie sich in einer Shell befinden, ist es sinnvoll, eine Methode wie in der Antwort von mikeserv zu verwenden, da dies das Starten des Prozesses für spart
tail
.)Echte Unicode-Zeichen?
Nun fragen Sie nach den letzten drei Zeichen . Das gibt Ihnen diese Antwort nicht: Sie gibt die letzten drei Bytes aus !
Solange jedes Zeichen ein Byte ist,
tail -c
funktioniert es einfach. So ist es verwendet werden kann , wenn der Zeichensatz istASCII
,ISO 8859-1
oder eine Variante.Wenn Sie eine Unicode-Eingabe haben, wie im allgemeinen
UTF-8
Format, ist das Ergebnis falsch:In diesem Beispiel sind
UTF-8
die griechischen Zeichen alpha, beta und gamma mit zwei Bytes lang:Die Option
-m
kann mindestens die echten Unicode-Zeichen zählen:Ok, die letzten 6 Bytes geben uns die letzten 3 Zeichen:
So
tail
bietet keine Unterstützung für allgemeine Zeichen Handhabung und versucht es nicht einmal (siehe unten): Es behandelt variabler Größe Linien, aber keine variable Größe Zeichen.Sagen wir es so: Es
tail
ist genau richtig für die Struktur des Problems, aber falsch für die Art der Daten.GNU coreutils
Suchen Sie weiter, es stellt sich heraus, der dich GNU coreutils, die Sammlung von grundlegenden Werkzeuge wie
sed
,ls
,tail
undcut
ist noch nicht vollständig internationalisiert. Dabei geht es hauptsächlich um die Unterstützung von Unicode.Wäre zum Beispiel
cut
ein guter Kandidat, um hier zur Charakterunterstützung anstelle von Tail zu verwenden. Es gibt Optionen zum Bearbeiten von Bytes oder Zeichen-c
(--bytes
) und-m
(--chars
);Nur das
-m
/--chars
ist ab Versioncut (GNU coreutils) 8.21
2013nicht implementiert!
Von
info cut
:Siehe auch diese Antwort zu Kann nicht `cut -c` (` --characters`) mit UTF-8 verwendet werden? .
quelle
cut
Lösung scheint es nicht zu sein.tail
mit Bytes und nicht mit Zeichen umgegangen werden soll. Ich habe einmal einen Patch gemacht, um eine neue Option hinzuzufügen, mit der auch Charaktere ausgewählt werden können, aber ich glaube, das wurde nie zusammengeführt: - /tail -c3 -n10 /var/log/syslog
tail -c3 -n10 /var/log/syslog
fragt nach den letzten 10 Zeilen, und das funktioniert bei mir. Sie verwenden die Option-c3
und anschließend die widersprüchliche Option-n10
. Die spätere Option hat Priorität.Wenn Sie Ihr Text in einem Shell - Variable genannt ist
STRING
, können Sie dies in einem tunbash
,zsh
odermksh
Shell:Oder
Das hat auch den Vorteil, mit ksh93 zu arbeiten, von dem diese Syntax stammt.
Der Punkt ist, dass das
:
vom getrennt werden muss-
, sonst wird es zum${var:-default}
Operator der Bourne-Shell.Die äquivalente Syntax in den
zsh
oderyash
Shells lautet:quelle
${STRING:(-3):3}
(unter Angabe des Längenfeldes )${STRING: -3}
(mit einem Leerzeichen zwischen:
und-
) oder${STRING: -3:3}
.3
etwas umstritten, da hier nach "den drei Zeichen vom dritten bis einschließlich zum letzten Zeichen" gefragt wird, was in der Praxis mit "Alle Zeichen ab dem dritten bis zum letzten Zeichen" identisch ist ".Verwenden von
awk
:quelle
Wenn sich die Zeichenfolge in einer Variablen befindet, können Sie Folgendes tun:
Das entfernt die letzten drei Zeichen vom Wert von
$var
like:... und dann von allem den Kopf
$var
abziehen, aber wie wurde nur abgezogen:Diese Methode hat ihre Vor- und Nachteile. Auf der positiven Seite ist es vollständig POSIX-portabel und sollte in jeder modernen Shell funktionieren. Wenn
$var
nicht mindestens drei Zeichen enthalten sind , wird nur die\n
nachfolgende ewline gedruckt. Wenn Sie es in diesem Fall drucken möchten , benötigen Sie einen zusätzlichen Schritt wie:Auf diese Weise
$last3
ist immer nur leer, wenn$var
3 oder weniger Bytes enthalten sind. Und$var
wird immer nur ersetzt,$last3
wenn$last3
leer ist oderunset
- und wir wissen, es liegt nichtunset
daran, dass wir es nur gesetzt haben.quelle
printf
Formatzeichenfolgen nicht?${VARNAME:(-3)}
(voraussetzenbash
)?bash
wie in jeder anderen Shell, die POSIX-Kompatibilität beansprucht.csh
ist nicht unter den modernen, POSIX-kompatible Shells ich hier erwähnen, leider. Die POSIX-Shell-Spezifikation wurde nachksh
dem Vorbild erstellt, das sich aus einer Kombination der beidencsh
und der traditionellen Bourne-Shells zusammensetzt.ksh
integrierte sowohlcsh
die hervorragende Jobsteuerungsfunktionalität als auch die I / O-Umleitung der alten Bourne-Stile. Es wurden auch einige Dinge hinzugefügt - wie die oben gezeigten Konzepte zur String-Manipulation.csh
Soweit ich weiß, wird dies wahrscheinlich in keinem traditionellen System funktionieren. Es tut mir leid, das zu sagen.Sie können dies tun, aber das ist ein wenig ... übertrieben:
quelle
Die kugelsichere Lösung für utf-8 Saiten:
Oder benutze:
um den fehlerhaften Umgang mit Daten zu verhindern.
Beispiel:
Gibt so etwas aus:
Hängt nicht von den Gebietsschemaeinstellungen ab (dh funktioniert mit
LC_ALL=C
).Bash
,sed
,grep
,awk
,rev
Benötigen etwas wie folgt aus :LC_ALL=en_US.UTF-8
Gemeinsame Lösung:
Sie können die Codierung mit uchardet erkennen . Siehe auch verwandte Projekte .
Sie können mit Encode in Perl, Codecs in Python 2.7 decodieren / codieren
Beispiel :
Extrahieren Sie die letzten drei Zeichen aus der Zeichenfolge utf-16le und konvertieren Sie diese Zeichen in utf-8
Siehe auch: perlunitut , Python 2 Unicode HOWTO
quelle
echo
ist Ihre kugelsichere Quelle?decode/encode
ist meine kugelsichere Quelle. Meine Antwort aufgeräumt.LC_ALL=C
weil das eine sehr "blöde" Einstellung ist, aber es kann brechen, wenn Sie versuchen, eine UTF-8-Zeichenfolge an SHIFT-5 oder eine SHIFT-5-Zeichenfolge an KOI8 usw. zu übergeben.perl -CAO -e 'print substr($ARGV[0], -3)'
funktioniert gut.A
Es wird erwartet, dass die @ ARGV-Elemente Zeichenfolgen sind, die in UTF-8 codiert sind,O
STDOUT in UTF-8.utf8_str
Was ist mit "expr" oder "rev"?
Eine Antwort ähnlich der von @ G-Man :
expr "$yourstring" : '.*\(...\)$'
Sie hat den gleichen Nachteil wie die grep-Lösung.Ein bekannter Trick ist, "cut" mit "rev" zu kombinieren:
echo "$yourstring" | rev | cut -n 1-3 | rev
quelle
rev
Lösung ähneltGröße der Zeichenkette ermitteln mit:
Dann erhalten Sie den Teilstring des letzten n-Zeichens:
Beispielsweise:
Würde geben:
quelle
tail -n 1 revisions.log | awk '{print substr ($ 0, 0, Länge ($ 0) - (Länge ($ 0) -13)}'
Wenn Sie die ersten dreizehn Zeichen von Anfang an drucken möchten
quelle
printf funktioniert nicht, wenn der String Leerzeichen enthält.
Unten Code für Zeichenfolge mit Leerzeichen
quelle
printf
es nicht funktioniert, dann machen Sie etwas sehr Falsches.printf $str
(anstattprintf "$str"
oderprintf '%s' "$str"
). Und ja,printf $str
ist sehr falsch. (echo -n $str
ist nicht viel besser.)