sed Whitespace passende Verwirrung

7
echo ' 1 2     3  '|sed 's/[[:space:]]*/_/g'

Ich möchte _1_2_____3__als Ausgabe sehen. Stattdessen sehe ich _1_2_3_als Ausgabe. Was mache ich falsch??

BEARBEITEN
Die andere Sache, die mich verwirrt und die ich im obigen Beispiel vergessen habe, ist, warum dies:

echo ' test1 test2  ' | sed 's/[[:space:]]*/_/g'

zeigt dies:

_t_e_s_t_1_t_e_s_t_2_

Wie kann [[:space:]]zwischen tund eund s... übereinstimmen ?

BenjiWiebe
quelle
1
Die gepostete Antwort beantwortet das auch schon. * entspricht 0 oder mehr Leerzeichen.
Leiaz
@Leiaz Hmmm .... daran habe ich nicht gedacht. Wie kann ich einen oder mehrere abgleichen?
BenjiWiebe
Mit +echo ' test1 test2 ' | sed 's/[[:space:]]\+/_/g'
Leiaz
1
@Leiaz: Zur 's/[[:space:]]\{1,\}/_/g'Portabilität verwenden.
Cuonglm
@Leiaz Oh ja ... es ist zu lange her, dass ich Regex studiert habe. Ich erinnere mich jetzt an '+'.
BenjiWiebe

Antworten:

14

Weil Sie verwenden *, was bedeutet, dass es 0 oder mehr Leerzeichen entspricht. Null oder mehrere Leerzeichen werden also durch einen Unterstrich ersetzt _.

Versuchen:

$ echo ' 1 2     3  ' | sed 's/[[:space:]]/_/g'
_1_2_____3__

Denken Sie daran, dass dies [[:space:]]auch mit Tabulator, Zeilenumbruch und Wagenrücklauf übereinstimmt.

Hinweis

cuonglm
quelle
5

Sie haben bereits eine Antwort, aber ich möchte darauf hinweisen, dass es in einem so einfachen Szenario nicht nötig ist, sich etwas vorzustellen:

$ echo ' 1 2     3  ' | sed 's/ /_/g'
_1_2_____3__

Wenn Sie nur Leerzeichen und Tabulatoren ersetzen möchten, können Sie auch das Konstrukt [\ t] verwenden:

$ echo -e " 1\t2     3  " | sed 's/[ \t]/_/g'
_1_2_____3__
jimmij
quelle
1

Die Frage bezieht sich explizit auf sed und ist eine sehr gültige Frage zur sed-Regexp-Syntax.

Für den Fall, dass es bei der zugrunde liegenden Frage darum geht, Leerzeichen durch _wirklich zu ersetzen , finden Sie hier eine alternative Antwort, bei der das "richtige Werkzeug für den Job" zum Übersetzen von Zeichen verwendet wird tr. ( man tr).

Der Befehl tr abc 123ersetzt die Zeichen der ersten Liste durch die entsprechenden Zeichen in der zweiten. Somit tr ' ' _ersetzt Raum durch Strich.

$ echo ' 1 2     3  ' | tr ' ' _
_1_2_____3__


Um den allgemeineren Fall zu zeigen, einschließlich verschiedener Arten von Leerzeichen wie in Ihrem Beispiel, ist
hier die Ausgabe, um nur das normale Leerzeichen ' 'zum Vergleich zu übersetzen:

echo ' 1 2     3  x\ny\tz' | tr ' ' _        
_1_2_____3__x
y       z

Und hier ist die Ausgabe bei der Übersetzung aller Zeichen der Klasse: space: to _:

echo ' 1 2     3  x\ny\tz' | tr '[:space:]' _
_1_2_____3__x_y_z_

(Beachten Sie, dass am Ende der Ausgabe kein Zeilenumbruch steht - und _nach dem z.).
Dies kann explizit als tr ' \t\n' _die Kurzform von geschrieben werden tr ' \t\n' ___.

$ echo ' 1 2     3  x\ny\tz' | tr ' \t\n' _    
_1_2_____3__x_y_z_
Volker Siegel
quelle
Ich weiß von tr. Ich werde das Beispiel, das ich ursprünglich gepostet habe, für immer bereuen. Ich habe mich speziell gefragt, wie ich eine Folge von Leerzeichen durch ein Zeichen ersetzen kann , obwohl ich das nur schlecht erklärt habe.
BenjiWiebe
Ich habe mein eigentliches Problem zunächst wirklich nicht gepostet , nur einen Teil davon. Ich dachte, ich könnte das Hauptproblem herausfinden, wenn ich das rätselhafte Verhalten meines ersten Beispiels überwinden könnte.
BenjiWiebe
Oh, du warst klar genug, dass du nach sed fragst; Aber selbst wenn die Antwort für Sie nicht hilfreich ist, kann sie jemand anderem beim Lesen der Fragen und Antworten helfen. Jemand, der sedwie in den Antworten verwendet, sollte zumindest wissen, dass es dafür ein viel einfacheres Werkzeug gibt.
Volker Siegel