Zum Beispiel gegeben:
USCAGoleta9311734.5021-120.1287855805
Ich möchte nur extrahieren:
US
Zum Beispiel gegeben:
USCAGoleta9311734.5021-120.1287855805
Ich möchte nur extrahieren:
US
Antworten:
Wenn Sie die bash
Shell verwenden (und dies scheint, basierend auf Ihren Kommentaren), ist es wahrscheinlich die effizienteste Methode, die Sub-String-Variante der Parametererweiterung zu verwenden:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Dies short
werden die ersten beiden Zeichen von sein long
. Wenn long
es kürzer als zwei Zeichen ist, short
ist es identisch.
Diese In-Shell-Methode ist normalerweise besser, wenn Sie viel tun (wie Sie bereits erwähnt 50.000 Mal pro Bericht), da kein Aufwand für die Prozesserstellung anfällt. Alle Lösungen, die externe Programme verwenden, leiden unter diesem Aufwand.
Wenn Sie auch eine Mindestlänge sicherstellen möchten , können Sie diese vorab mit etwas ausfüllen:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Dies würde sicherstellen, dass rechts weniger als zwei Zeichen mit Punkten (oder etwas anderem, nur durch Ändern des beim Erstellen verwendeten Zeichens tmpstr
) aufgefüllt werden . Es ist nicht klar, dass Sie das brauchen, aber ich dachte, ich würde es der Vollständigkeit halber einfügen.
Es gibt jedoch eine Reihe von Möglichkeiten, dies mit externen Programmen zu tun (z. B. wenn Ihnen diese nicht zur bash
Verfügung stehen). Einige davon sind:
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
Die ersten beiden ( cut
und head
) sind für eine einzeilige Zeichenfolge identisch - beide geben Ihnen im Grunde nur die ersten beiden Zeichen zurück. Sie unterscheiden sich darin, cut
dass Sie die ersten beiden Zeichen jeder Zeile und head
die ersten beiden Zeichen der gesamten Eingabe erhalten
Der dritte verwendet die awk
Sub-String-Funktion, um die ersten beiden Zeichen zu extrahieren, und der vierte verwendet sed
Erfassungsgruppen (mit ()
und \1
), um die ersten beiden Zeichen zu erfassen und die gesamte Zeile durch diese zu ersetzen. Sie sind beide ähnlich cut
- sie liefern die ersten beiden Zeichen jeder Zeile in der Eingabe.
Nichts davon ist von Bedeutung, wenn Sie sicher sind, dass Ihre Eingabe eine einzelne Zeile ist. Alle haben den gleichen Effekt.
printf '%s'
für den echo
Fall, dass es seltsame Zeichen in der Zeichenfolge gibt: stackoverflow.com/a/40423558/895245 Für die POSIX besessen: head -c
ist nicht POSIX cut -c
und awk substr
sind sed \1
nicht sicher.
Der einfachste Weg ist
${string:position:length}
Wo dies $length
Teilzeichenfolge aus $string
at extrahiert $position
.
Dies ist eine eingebaute Bash, so dass kein Awk oder Sed erforderlich ist.
Sie haben mehrere gute Antworten bekommen und ich würde mit dem Bash builtin mich gehen, aber da Sie gefragt , sed
und awk
und ( fast ) niemand sonst Lösungen auf ihnen angeboten basiert, biete ich Ihnen diese:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
und
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
Der awk
eine sollte ziemlich offensichtlich sein, aber hier ist eine Erklärung des sed
einen:
substr($0,1,2)
.
Wenn Sie dabei sind bash
, können Sie sagen:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
Dies kann genau das sein, was Sie brauchen ...
Nur grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
Option entfernen , um sie zu verkürzen. Alle regulären Ausdrücke werden dieses Muster verstehen.
Sie können verwenden printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Ziemlich spät, aber hier ist es
sed 's/.//3g'
Oder
awk NF=1 FPAT=..
Oder
perl -pe '$_=unpack a2'
Wenn Sie Shell-Scripting verwenden möchten und sich nicht auf Nicht-Posix-Erweiterungen (wie sogenannte Bashisms) verlassen möchten, können Sie Techniken verwenden, für die keine externen Tools wie grep, sed, cut, awk usw. erforderlich sind Machen Sie Ihr Skript weniger effizient. Möglicherweise sind Effizienz und Posix-Portabilität in Ihrem Anwendungsfall nicht wichtig. Falls dies jedoch der Fall ist (oder nur eine gute Angewohnheit ist), können Sie die folgenden beiden Zeichen einer Shell-Variablen mit der folgenden Methode zur Parametererweiterungsoption extrahieren:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Hierbei wird die Parametererweiterung "kleinstes Präfix" verwendet , um die ersten beiden Zeichen (dies ist der ${var#??}
Teil) zu entfernen , und dann die Parametererweiterung "kleinstes Suffix" (der ${var%
Teil), um die Zeichenfolge mit Ausnahme der ersten zwei Zeichen aus dem Original zu entfernen Wert.
Diese Methode wurde zuvor in dieser Antwort auf die Frage "Shell = Überprüfen, ob die Variable mit # beginnt" beschrieben. Diese Antwort beschreibt auch einige ähnliche Parametererweiterungsmethoden, die in einem etwas anderen Kontext verwendet werden können als der, der hier für die ursprüngliche Frage gilt.
Wenn Ihr System eine andere Shell verwendet (nicht bash
), Ihr System jedoch eine andere bash
, können Sie die inhärente Zeichenfolgenmanipulation von weiterhin verwenden, bash
indem Sie bash
eine Variable aufrufen :
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
bash
wenn Sie sie noch nicht verwenden.
Nur um Spaß zu haben, füge ich einige hinzu, die zwar überkompliziert und nutzlos sind, aber nicht erwähnt wurden:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
if mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
würde US drucken
Dabei ist 0 die Startposition und 2 die Anzahl der zu lesenden Zeichen
awk
. Entschuldigung, ich konnte es zuerst nicht sagen.
Ist es das, wonach du suchst?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
ref: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'