Wie kann man Zeichen vor einer Zeichenfolge löschen / löschen?

12

Ich habe eine Zeichenfolge, die ich manipulieren möchte. Die Zeichenfolge ist, H08W2345678wie ich sie manipulieren kann, damit die Ausgabe gerecht ist W2345678.

Ebenso, wenn ich die letzten 4 Zeichen löschen wollte, H08W2345678damit ich bekomme, H08W234wie würde ich das tun?

3kstc
quelle
1
Es gibt viele Möglichkeiten, Zeichenfolgen zu manipulieren. Gibt es einen bestimmten Grund für die Verwendung sed?
don_crissti
@don_crissti Kein Grund, abgesehen von mangelnder Erfahrung. Alle Alternativen sind willkommen ...
3kstc
@don_crissti, die Geschichte: Aus einer herausgefilterten CSV-Datei nehme ich einen der Parameter aus einer Zeile, die bearbeitet werden muss, H08W2345678und W2345678dieser Wert wird mit einem anderen Datum in eine gesendete E-Mail eingefügt. Das E-Mail-Versenden erfolgt mit cron.
3kstc
@don_crissti awking es. Ich erstelle ein Array und ändere dann jedes Element innerhalb des Arrays (alle unterschiedlich - dh ändere den Epochenzeitpunkt in Sekunden auf ein Datum usw.)
3kstc
2
Sie können solche Sachen mit awk machen:printf %s\\n "XX,H08W2345678,YY" | awk -F, '{print substr($2, 4); print substr($2, 1, length($2)-4)}'
don_crissti

Antworten:

17

Verwenden Sie einfach bash (oder ksh93woher diese Syntax kommt oder zsh):

string="H08W2345678"

echo "${string:3}"
W2345678

echo "${string:0:-4}"
H08W234

Weitere Informationen zur Manipulation von Saiten finden Sie im Wooledge-Wiki .

Jasonwryan
quelle
Dies erfordert Bash 4.2 oder höher. Lesen Sie diese alte Kopie des Bash-Referenzhandbuchs, Abschnitt 3.5.3, '' Shell Parameter Expansion '' oder die Antwort von Chicks hier , um die alte Einschränkung zu sehen („Die Länge muss eine Zahl größer oder gleich Null ergeben.“). … (Fortsetzung)
Scott
(Fortsetzung)… siehe Bash-Änderungen (im Bash Hackers-Wiki) (scrollen Sie zum Ende des Abschnitts) oder Bash-News bei der Organisation Technology Infrastructure Services der Case Western Reserve University (Suche nach „zu Bash-4.2 hinzugefügt“). und scrollen Sie dann nach unten zu "q."), um die Revision zu sehen. ... ... ... ...  "${string:0:${#string}-4}" funktioniert in der Bash Version 4.1 , solange die Länge von $stringmindestens 4
Scott
PS Dies wird auch bei Zeichenfolgen ersticken abc-e, bei denen Sie beim Ablegen der ersten drei Zeichen übrig bleiben -e(weil Sie echo -enicht das tun, was Sie möchten).
Scott
8
$ echo "H08W2345678" | sed 's/^.\{3\}//'
W2345678

sed 's/^.\{3\}//'findet die ersten drei Zeichen durch ^.\{3\}und ersetzt durch leer. Hier ^.stimmt jedes Zeichen am Anfang der Zeichenfolge überein ( ^gibt den Anfang der Zeichenfolge an) und \{3\}stimmt genau dreimal mit dem vorherigen Muster überein. Also ^.\{3\}werden die ersten drei Zeichen übereinstimmen.

$ echo "H08W2345678" | sed 's/.\{4\}$//'
H08W234

In ähnlicher Weise sed 's/.\{4\}$//'werden die letzten vier Zeichen durch Leerzeichen ersetzt ( $gibt das Ende der Zeichenfolge an).

heemayl
quelle
1
Könnten Sie bitte das erklären 's/^.\{3\}//'und 's/.\{4\}$//'da ich noch sed lerne, vielen Dank
3kstc
@ 3kstc: Bitte überprüfen Sie die Änderungen
heemayl
1
Für nur ein paar Zeichen würde ich verwenden, ...anstatt .\{3\}(für mich) ist es einfacher zu lesen: sed -e 's/^...//' -e 's/....$//' oder in einem einzelnen Ausdruck mit Wechsel : sed -r 's/^...|....$//g'. Wenn mehr als ein paar Zeichen gelöscht werden müssten, würde ich /.\{17}\/stattdessen den Ausdruck verwenden /.............../.
Johnny
Dies verhält sich schlecht, wenn die Zeichenfolge -eoder ist -n. Natürlich ist die Bedeutung von "die letzten 4 Zeichen löschen" für eine Zeichenfolge mit weniger als 4 Zeichen undefiniert, aber wenn jemand dies anpassen möchte, um das erste oder letzte Zeichen zu löschen, kann dies explodieren.
Scott
2

Wenn Sie eine Datei haben, in der jede Zeile eine Zeichenfolge mit elf Zeichen (oder was auch immer) ist, die Sie zerlegen möchten, sedist dies das zu verwendende Werkzeug. Es ist in Ordnung, eine einzelne Saite zu manipulieren, aber es ist übertrieben. Für eine einzelne Zeichenfolge ist Jasons Antwort wahrscheinlich die beste, wenn Sie Zugriff auf Bash-Version 4.2 oder höher haben. Die Syntax und scheinen jedoch nur für bash eindeutig zu sein (well, bash, ksh93, mksh und zsh). Ich sehe sie nicht in den Open Group- Basisspezifikationen für die Shell-Befehlssprache . Wenn Sie mit einer POSIX-kompatiblen Shell nicht weiterkommen, die keine Teilstringerweiterung (Extraktion) unterstützt, können Sie diese verwenden${parameter:offset}${parameter:offset:length}

$ printf "%s\n" "${string#???}"
W2345678

$ printf "%s\n" "${string%????}"
H08W234

Verwenden Sie printfstatt echo, um sich vor Zeichenfolgen wie zu schützen abc-e, bei denen Sie beim Ablegen der ersten drei Zeichen übrig bleiben -e (und echo -enicht das tun, was Sie möchten).

Und wenn Sie überhaupt keine Shell der Bourne-Familie verwenden (oder ein altes Pre-POSIX-System verwenden), sollten diese weiterhin funktionieren:

$ expr " $string" : ' ...\(.*\)'
W2345678

$ expr " $string" : ' \(.*\)....'
H08W234

Der zusätzliche führende Raum ist , um Probleme mit den Werten zu vermeiden $string Darin sind tatsächliche exprBetreiber (zB +,  /,  indexoder match) oder Optionen (zB  --, --helpoder  --version).

Scott
quelle
@ Stéphane Chazelas: (1) Danke, dass du mich an eine Falle erinnert hast, die ich vor ungefähr 40 Jahren kannte und die ich irgendwie vergessen habe. (2) Ich habe das immer mit gelöst X; zB , expr "X$string" : 'X...\(.*\)'. IMO, das ist leichter zu lesen und zu verstehen. Gibt es ein Problem damit oder einen Grund, einen Platz zu bevorzugen? (3) Heute habe ich gelernt, dass das expr + "$string" : '...\(.*\)'jetzt funktioniert. Ich erinnere mich nicht daran von vor 40 Jahren; Ist es weit genug verbreitet, um sicher zu empfehlen? (4) Sie haben eine Notiz zu Jasonwryans Antwort und eine Kleinigkeit zu Heemayls Antwort verpasst.
Scott
AFAIK, das expr +ist nur GNU (funktioniert nicht unter Solaris oder FreeBSD AFAICS). Ich verwende Leerzeichen anstelle von x, da es weniger wahrscheinlich ist, dass einige exprImplementierungen Operatoren haben, die mit Leerzeichen beginnen als mit, xund weil es weniger wahrscheinlich ist, dass Elemente zusammengestellt werden, die mit Leerzeichen beginnen als mit x. Aber dann wird mir klar, dass es wahrscheinlich keine gute Wahl für den expr " $a" "<" " $b"String-Vergleich ist, da einige Implementierungen einen numerischen Vergleich durchführen, wenn $a/ $bwie Zahlen aussehen. Vielleicht expr "@@$a"...oder expr "x $a"könnte sicherer sein.
Stéphane Chazelas
0

Mit:

string="H08W2345678"

Das Zuordnen von 3 oder 4 Zeichen scheint einfach zu sein (für die meisten Muscheln):

$ printf '%s\t%s\n' "${string#???}" "${string%????}"
W2345678      H08W234

Verwenden Sie für ältere Muscheln (wie die Bourne-Muschel):

$ string=H08W2345678

$ expr " ${string}" : " ...\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\)...." '
H08W234

Wenn eine numerische Anzahl von Zeichen benötigt wird, verwenden Sie:

$ expr " ${string}" : " .\{3\}\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\).\{4\}" '
H08W234

Natürlich funktionieren diese Regex auch mit sed, awk und bash 3.0+:

$ echo "$string" | sed 's/^.\{3\}//'
W2345678

$ echo "$string" | sed 's/.\{4\}$//'
H08W234

$ echo "$string" | awk '{sub(/^.{3}/,"")}1'
W2345678

$ echo "$string" | awk '{sub(/.{4}$/,"")}1'
H08W234

$ r='^.{3}(.*)$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
W2345678

$ r='^(.*).{4}$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
H08W234
Isaac
quelle
-1

Wie kann man Zeichen vor einer Zeichenfolge löschen / löschen?

Ich habe eine Zeichenfolge, die ich manipulieren möchte. Die Zeichenfolge lautet H08W2345678. Wie kann ich sie manipulieren, sodass die Ausgabe nur W2345678 ist?

echo "H08W2345678" | cut -c 4-
aexl
quelle
Dies beantwortet nur die Hälfte der Frage.
Kusalananda
Ich halte Ihre Ablehnung für unfair. Diese Hälfte beantwortet die Frage, die ich hatte, als ich posix googelte, um die ersten Zeichen zu entfernen, und diese Seite wurde in den Suchergebnissen angezeigt . Darüber hinaus deckt dieser Seitentitel nur genau die Hälfte der Frage ab. Ich bin zurückgekommen und habe dazu beigetragen, als ich die Lösung gefunden habe, die mir gefallen hat - ich denke, dieser Job cutist viel eleganter als alles andere auf dieser Seite.
Aexl