Wie ersetze ich einen Teilstring aus einer Variablen?


7

Ich versuche, Zeichen aus einer Zeichenfolgenvariablen zu entfernen. Es funktioniert bei mir sedso:

MYVAR=--23ho02123ware38384you443d34o3434ingtod38384day-%§*#sfrf
echo ${MYVAR} | sed -e 's/[a-z][a-z0-9\-]*//g'

und ich bekomme:

 --23%§*#

das ist was ich suche. Die Zeichenfolge sollte mit einem Buchstaben beginnen und nur Buchstaben, Ziffern und einen Bindestrich (-) enthalten. Gibt es eine Möglichkeit, dies durch bashErsetzen von Zeichenfolgen zu erreichen ?

MYVAR=${MYVAR/[a-z][a-z0-9-]*/ }

Ich habe mehrere Kombinationen ausprobiert, aber keine davon funktioniert wie erwartet.


Das Ersetzen von Bash-Strings unterstützt KEINEN regulären Ausdruck! Beim Ersetzen von Bash-Strings wird Globbing ausgeführt, wobei * gleich * in Regex ist. check en.wikipedia.org/wiki/Glob_(programming)
— frams

Antworten:


10

Sie müssten die erweiterten ksh-Glob-Operatoren (von denen eine Teilmenge in bashwith shopt -s extglobund with zshwith verfügbar ist set -o kshglob) verwenden, um das Äquivalent regulärer Ausdrücke zu erhalten (allerdings mit einer anderen Syntax: *(x)für das Äquivalent von x*hier):

shopt -s extglob # for bash
# set -o kshglob # for zsh
printf '%s\n' "${MYVAR//[[:alpha:]]*([[:alnum:]-])/}"

Oder mit zsh extendedglobs, wo das Äquivalent von regulärem Ausdruck *ist #:

set -o extendedglob
printf '%s\n' ${MYVAR//[[:alpha:]][[:alnum:]-]#}

Ein paar Anmerkungen:

  • ${var/pattern/replacement}ersetzt nur das erste Vorkommen. Verwenden ${var//pattern/replacement}jedes Vorkommen zu ersetzen (wie mit der gFahne in sed‚s - sBefehl).
  • Sie hatten Ihren Ersatz zu einem Leerzeichen gemacht. Verwenden Sie ${var//pattern/}(oder ${var//pattern}), um durch die leere Zeichenfolge zu ersetzen.
  • Sie möchten keine echobeliebigen Zeichenfolgen ausgeben
  • Außer in zshmüssen Variablenerweiterungen in Listenkontexten in Anführungszeichen gesetzt werden
  • Das Verhalten würde sich von Ihrem sedAnsatz unterscheiden, wenn die Variable Zeilenumbrüche enthält.
  • [a-z]Übereinstimmungen, die zwischen Zeichen (Elemente in einigen Werkzeugen Kollationieren) aund zdie Liste der sich ändert mit den Lokalisierungs, das System und das Werkzeug (beispielsweise [a-z]mit bash-4.3in einem en_GB.UTF-8locale auf einem GNU System entspricht A, X, é, Ẃ, aber nicht Z). Dies schließt im Allgemeinen die 26 Kleinbuchstaben des englischen Alphabets ein, muss aber nicht. [[:alpha:]]Enthält Zeichen (oder Sortierelemente), die in Ihrem Gebietsschema als alphabetisch (unabhängig von der Groß- und Kleinschreibung) betrachtet werden. Wenn Sie nur mit den 26 englischen Buchstaben übereinstimmen möchten, verwenden [abcdefghijklmnopqrstuvwxyz]oder korrigieren Sie das Gebietsschema auf C( LC_ALL=C) und verwenden Sie [a-z]oder nur [[:lower:]]für englische Kleinbuchstaben oder [a-zA-Z]/[[:alpha:]] für jeden englischen Brief.
  • [a-z0-9\-]in sedstimmt mit dem Backslash-Zeichen überein, verwenden Sie [a-z0-9-]stattdessen (das -muss das erste oder letzte sein, um wörtlich genommen zu werden).

könnte auch hinzufügen, dass //für gFlag im Gegensatz zu /von OP verwendet wird, äquivalent ist und dass das letzte Leerzeichen in OPs Versuch das übereinstimmende Muster durch Leerzeichen ersetzt
— Sundeep

1
Vielen Dank Stéphane Chazelas, es funktioniert wie ein Zauber, auch ohne die erweiterten ksh-Glob-Operatoren shopt -s extglob. Best
— dings

KORREKTUR: shopt extglob war auf meinem Computer bereits aktiviert, also brauche ich es wirklich!
— Nochmals

schöne Erklärung! Ich habe das Leerzeichen in meinem Ersatz gesehen, das ich bereits korrigiert habe. Ich verwende das Gebietsschema en_US.UTF-8 auf dem System, exportiere aber de_DE.UTF-8, wenn ich das Skript ausführe, um europäische Buchstaben in ASCII-Zeichen konvertieren zu können, da en_US.UTF-8 sie nicht korrekt konvertiert. Neue Zeilenzeichen sind kein Problem, da diese Zeichenfolge eine Benutzeranmeldung ist, die in der Bash-Eingabeaufforderung eingegeben wurde. Dies ist Teil eines riesigen Skripts, das ich geschrieben habe, um LDAP-Konten auf zwei verschiedenen Servern zu erstellen, und ich versuche, das Skript zu zwingen, nur gültige Formatanmeldungen zu akzeptieren. Vielen Dank.
— Dings

1
@Sundeep, guter Punkt. Ich habe jetzt diese Notizen und ein paar mehr aufgenommen.
— Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.