Vielen Dank an alle. Am Ende habe ich 'cut -c1-2' verwendet, ehrlich gesagt wusste ich nicht einmal, dass 'cut' da ist. Ich möchte sagen, dass ich ziemlich erfahren in der Kommandozeile bin - aber anscheinend muss ich noch viel lernen.
Greg
1
@ Greg, sei dir nur bewusst, dass das Schneiden als separater Prozess ausgeführt wird - es ist langsamer als die interne Bash-Lösung, die ich in meiner Antwort daneben gepostet habe. Das macht keinen Unterschied, es sei denn, Sie verarbeiten große Datenmengen, aber Sie müssen dies berücksichtigen.
Paxdiablo
Bearbeiten Eigentlich denke ich, dass diese Codezeile wahrscheinlich ungefähr 50.000 Mal pro Bericht ausgeführt wird. Ich könnte mich also für die interne Bash-Methode entscheiden, die, wie Sie sagten, einige dringend benötigte Ressourcen spart.
Wenn Sie die bashShell 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 shortwerden die ersten beiden Zeichen von sein long. Wenn longes kürzer als zwei Zeichen ist, shortist 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 bashVerfü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 ( cutund head) sind für eine einzeilige Zeichenfolge identisch - beide geben Ihnen im Grunde nur die ersten beiden Zeichen zurück. Sie unterscheiden sich darin, cutdass Sie die ersten beiden Zeichen jeder Zeile und headdie ersten beiden Zeichen der gesamten Eingabe erhalten
Der dritte verwendet die awkSub-String-Funktion, um die ersten beiden Zeichen zu extrahieren, und der vierte verwendet sedErfassungsgruppen (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.
Ich würde lieber verwenden, als printf '%s'für den echoFall, dass es seltsame Zeichen in der Zeichenfolge gibt: stackoverflow.com/a/40423558/895245 Für die POSIX besessen: head -cist nicht POSIX cut -cund awk substrsind sed \1nicht sicher.
Ciro Santilli 法轮功 冠状 病 六四 事件 7
1
@CiroSantilli print 改造 6 996ICU 六四 事件 Mit printf benötigen Sie nicht einmal ein zusätzliches Programm. Siehe meine Antwort .
bschlueter
60
Der einfachste Weg ist
${string:position:length}
Wo dies $lengthTeilzeichenfolge aus $stringat extrahiert $position.
Dies ist eine eingebaute Bash, so dass kein Awk oder Sed erforderlich ist.
Dies ist der kurze, süße und einfachste Weg, um den Teilstring zu bekommen.
Ani627
34
Sie haben mehrere gute Antworten bekommen und ich würde mit dem Bash builtin mich gehen, aber da Sie gefragt , sedund awkund ( fast ) niemand sonst Lösungen auf ihnen angeboten basiert, biete ich Ihnen diese:
echo "USCAGoleta9311734.5021-120.1287855805"| sed 's/\(^..\).*/\1/'
Der awkeine sollte ziemlich offensichtlich sein, aber hier ist eine Erklärung des sedeinen:
Ersatz "s /"
die Gruppe "()" von zwei beliebigen Zeichen ".." beginnend am Anfang der Zeile "^" und gefolgt von einem beliebigen Zeichen "." null oder mehrmals "*" wiederholt (die Backslashes werden benötigt, um einige der Sonderzeichen zu umgehen)
durch "/" den Inhalt der ersten (und in diesem Fall einzigen) Gruppe (hier ist der Backslash ein spezielles Escape, das sich auf einen übereinstimmenden Unterausdruck bezieht)
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.
Beste Antwort, sollte oben sein. Keine Gabeln, keine Bashismen. funktioniert auch mit kleinen Muscheln wie Dash.
Exore
1
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, bashindem Sie basheine 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;"
Dies verwendet dieselbe Methode wie die Hauptantwort und wird nur aufgerufen, bashwenn Sie sie noch nicht verwenden.
Palswim
Leider ist dies mit dem gesamten Aufwand für das Aufrufen eines anderen Prozesses verbunden, aber manchmal ist dieser Aufwand weniger wichtig als Einfachheit und Vertrautheit.
Palswim
1
Nur um Spaß zu haben, füge ich einige hinzu, die zwar überkompliziert und nutzlos sind, aber nicht erwähnt wurden:
Angesichts der Tatsache, dass er / sie dies wahrscheinlich von der Shell aus aufruft, wäre eine bessere Formperl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'
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:Dies
short
werden die ersten beiden Zeichen von seinlong
. Wennlong
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:
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:Die ersten beiden (
cut
undhead
) 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 undhead
die ersten beiden Zeichen der gesamten Eingabe erhaltenDer dritte verwendet die
awk
Sub-String-Funktion, um die ersten beiden Zeichen zu extrahieren, und der vierte verwendetsed
Erfassungsgruppen (mit()
und\1
), um die ersten beiden Zeichen zu erfassen und die gesamte Zeile durch diese zu ersetzen. Sie sind beide ähnlichcut
- 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.
quelle
printf '%s'
für denecho
Fall, dass es seltsame Zeichen in der Zeichenfolge gibt: stackoverflow.com/a/40423558/895245 Für die POSIX besessen:head -c
ist nicht POSIXcut -c
undawk substr
sindsed \1
nicht sicher.Der einfachste Weg ist
Wo dies
$length
Teilzeichenfolge aus$string
at extrahiert$position
.Dies ist eine eingebaute Bash, so dass kein Awk oder Sed erforderlich ist.
quelle
Sie haben mehrere gute Antworten bekommen und ich würde mit dem Bash builtin mich gehen, aber da Sie gefragt ,
sed
undawk
und ( fast ) niemand sonst Lösungen auf ihnen angeboten basiert, biete ich Ihnen diese:und
Der
awk
eine sollte ziemlich offensichtlich sein, aber hier ist eine Erklärung dessed
einen:quelle
substr($0,1,2)
.Wenn Sie dabei sind
bash
, können Sie sagen:Dies kann genau das sein, was Sie brauchen ...
quelle
Nur grep:
quelle
-P
Option entfernen , um sie zu verkürzen. Alle regulären Ausdrücke werden dieses Muster verstehen.Sie können verwenden
printf
:quelle
colrm - Spalten aus einer Datei entfernen
Um die ersten beiden Zeichen zu belassen, entfernen Sie einfach die Spalten ab 3
quelle
Ziemlich spät, aber hier ist es
Oder
Oder
quelle
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:
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.
quelle
Wenn Ihr System eine andere Shell verwendet (nicht
bash
), Ihr System jedoch eine anderebash
, können Sie die inhärente Zeichenfolgenmanipulation von weiterhin verwenden,bash
indem Siebash
eine Variable aufrufen :quelle
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:
quelle
quelle
if mystring = USCAGoleta9311734.5021-120.1287855805
würde US drucken
Dabei ist 0 die Startposition und 2 die Anzahl der zu lesenden Zeichen
quelle
awk
. Entschuldigung, ich konnte es zuerst nicht sagen.Ist es das, wonach du suchst?
ref: substr
quelle
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'