Verwenden Sie sed, um eine öffnende und schließende eckige Klammer um eine Zeichenfolge zu entfernen

18

Ich führe diesen Befehl in einer Bash-Shell unter Ubuntu 12.04.1 LTS aus. Ich versuche, sowohl die [als auch die ]Zeichen auf einen Schlag zu entfernen , dh ohne ein zweites Mal pfeifen zu müssen, um zu sedieren.

Ich weiß, dass eckige Klammern in einem regulären Ausdruck eine besondere Bedeutung haben, daher kann ich sie umgehen, indem ich ihnen einen Backslash voranstelle. Das Ergebnis, das ich erwartet hatte, war nur die Saite, 123aber die eckigen Klammern bleiben und ich würde gerne wissen, warum!

~$ echo '[123]' | sed 's/[\[\]]//'
[123]
Xhantar
quelle
Was ich letztendlich erreichen möchte, ist, einer Bash-Variablen alles zwischen den eckigen Klammern zuzuweisen, um es an einer anderen Stelle in meinem Bash-Skript zu verwenden. Wenn es also einen besseren Weg gibt, dies zu erreichen (vielleicht mit awk?), Lassen Sie es mich bitte wissen .
Xhantar
2
Nur als Kommentar hinzufügen: Sie können bashs PE-Funktion wie str='[123]'; str1=${str/\[/}; str2=${str1/\]}; echo $str2
folgt verwenden
1
@ val0x00ff - Pure Bash-Substitution .. danke! :) etwas neues gelernt.
Xhantar

Antworten:

23

Dies ist einfach, wenn Sie das Handbuch sorgfältig befolgen : Alle Mitglieder innerhalb einer Zeichenklasse verlieren (mit wenigen Ausnahmen) eine besondere Bedeutung. Und] verliert seine besondere Bedeutung, wenn es an erster Stelle in der Liste steht. Versuchen:

$ echo '[123]' | sed 's/[][]//g'
123
$

Das sagt:

  1. Ersetzen Sie innerhalb der äußeren [Klammern] eines der enthaltenen Zeichen, nämlich:
    • ] und
    • [
  2. Ersetzen Sie eine von ihnen durch die leere Zeichenfolge - daher die leere Ersatzzeichenfolge //,
  3. Ersetzen Sie sie überall ( global ) - daher das Finale g.

Auch hier ] muss in der Klasse sein , zuerst , wenn es enthalten ist.

Saparagus
quelle
11

Ich bin nicht sicher, warum das nicht funktioniert, aber das tut:

echo '[123]' | sed 's/\(\[\|\]\)//g'

oder dieses:

echo '[123]' | sed -r 's/(\[|\])//g'

Sie können auch einen anderen Ansatz wählen und die Zeichenfolge in den Klammern abgleichen (vorausgesetzt, die Zeichenfolge kann leicht abgeglichen werden und wird nicht durch die Klammern definiert):

echo '[123]' | egrep -o "[0-9]+"

Ich habe die gleichen Probleme mit Ihrer ursprünglichen Regex-Verwendung, grepdaher vermute ich, dass dies nicht nur eine sedSache ist.

Seltsamerweise führen diese zu unterschiedlichen Ergebnissen, aber eines davon entspricht genau Ihren Vorstellungen:

echo '[123]' | egrep -o '[^][]+'
123

echo '[123]' | egrep -o '[^[]]+'
3]

Wenden Sie dies auf Ihr Original an sed(und fügen Sie den /gModifikator hinzu, sodass beide Klammern entfernt werden):

echo '[123]' | sed 's/[][]//g'
123
Ladadadada
quelle
Ihr dritter Ansatz (egrep -o ...) scheint die sauberste Lösung für mein Problem zu sein. Ich werde immer nur ganze Zahlen zwischen den eckigen Klammern haben (und entschuldige, ich hätte das in meiner Frage erwähnen sollen), damit ich nicht auf irgendwelche Seltsamkeiten stoße, die ich denke. Vielen Dank!
Xhantar
3
Sie können auch Folgendes verwenden tr: echo '[123]' | tr -d '[]'- Vermeidet regexp-Verwechslungen bei der Flucht.
James O'Gorman
@ James O'Gorman - Interessant. Aus irgendeinem Grund dachte ich, dass trnur ein Zeichen gleichzeitig übersetzt werden kann, aber ich habe mich geirrt. Vielen Dank!
Xhantar
4

So entfernen Sie alles vor und nach den Klammern:

$ echo '[123]' | sed 's/.*\[//;s/\].*//;'
123

Wenn Ihre Daten so sind, bedeutet dies immer, dass sie mit eckigen Klammern beginnen und enden:

$ echo '[123]' | sed 's/.//;s/.$//;'
123
Guru
quelle
Die Daten, mit denen ich arbeite, beginnen und enden immer in eckigen Klammern. Ich würde immer noch gerne wissen, warum meine Lösung nicht funktioniert hat. Irgendwelche Ideen? Und gibt es eine Möglichkeit, dies zu tun, ohne 2x reguläre Ausdrücke anzugeben?
Xhantar
1
@Guru diese Lösung hat bei mir funktioniert, und was Xhantar betrifft, ist dies eine sehr späte Antwort, aber was ich aus Ihrem Code und dem Bash Beginners-Handbuch auf tldp.org sehen kann, haben Sie versucht, mehrere Suchen und Ersetzen durchzuführen, eines für '[' und das andere für ']', die nicht funktionieren, um zwei verschiedene Such- und Ersetzungsoptionen zu trennen, verwenden Sie das ";" oder die -e Optionen. 's / <suche> / <ersetze> / g; s / <suche> / <ersetze> / g 'ODER sed-es / <suche> / <ersetze> / g' -es / <suche> / <ersetze> / g '
ArunMKumar
1

Wenn Sie eine komplexere Zeichenfolge wie 'abcdef [123] ghijk' haben, können Sie auch den internen Bash-Befehl 'cut' verwenden, um Text nur in eckigen Klammern zu extrahieren:

$ echo 'abcdef[123]ghijk' | cut -d '[' -f 2 | cut -d ']' -f 1
123
valentt
quelle
1

Sie können die öffnende Klammer mit verlassen \[. Verwenden Sie für die schließende Klammer []].

user2428118
quelle