Ersetzen Sie alle Tabulatoren und Leerzeichen durch ein einzelnes Leerzeichen

23

Ich habe eine Zeichenfolge wie die folgende:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

Jetzt möchte ich alle Tabulatoren / Leerzeichen zwischen den Datensätzen durch ein einziges Leerzeichen ersetzen, damit ich es problemlos verwenden kann cut -d " "

Ich habe folgendes versucht:

sed "s/[\t[:space:]]+/[:space:]/g"

und verschiedene Varianten, aber konnte es nicht zum Laufen bringen. Irgendwelche Ideen?

Zulakis
quelle
Versuchen Sie: sed -r -e "s / [\ t \] + / / g"
RJS
Hat Ihre cutUnterstützung eine -wOption?
Kondybas

Antworten:

40

Verwenden sed -e "s/[[:space:]]\+/ /g"

Hier ist eine Erklärung:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

Als Ersatz möchten Sie nur ein Leerzeichen einfügen. [:space:]funktioniert dort nicht, da dies eine Abkürzung für eine Zeichenklasse ist und die Regex-Engine nicht weiß, welches Zeichen sie dort ablegen soll.

Das +muss in der Regex maskiert werden, da die Regex-Engine von sed +ein normales Zeichen ist, wohingegen \+es ein Metazeichen für 'ein oder mehrere' ist. Auf Seite 86 von " Beherrschen regulärer Ausdrücke" erwähnt Jeffrey Friedl in einer Fußnote, dass ed und grep geschützte Klammern verwendeten, weil "Ken Thompson der Ansicht war, dass reguläre Ausdrücke verwendet würden, um hauptsächlich mit C-Code zu arbeiten . " Ich gehe davon aus, dass er das Pluszeichen genauso empfand, daher die Notwendigkeit, es zu umgehen, um es als Metazeichen zu verwenden. Es ist leicht, sich davon auszulösen.

In sed Sie fliehen müssen +, ?, |, (, und ). oder verwende -r, um einen erweiterten regulären Ausdruck zu verwenden (dann sieht es aus wie sed -r -e "s/[[:space:]]\+/ /g"odersed -re "s/[[:space:]]\+/ /g"

Seestern
quelle
Entfernt dies auch Tabs? Können Sie erklären, warum Sie \+anstelle von nur verwenden +?
Zulakis
Okay ich verstehe. [[: space:]] ist gleich [\ t \ r \ n \ v \ f]. Aber können Sie bitte erklären, warum Sie verwenden\+
Zulakis
3
[[: space:]] ist gleichbedeutend mit '\ s', daher ist die kürzere Version "s / \ s \ + / / g"
3.
2
Grundlegende reguläre Ausdrücke verwenden einen Backslash vor einem Pluszeichen, wenn sie "eines oder mehrere der vorherigen Zeichen oder Gruppen" bedeuten (Quelle: developer.apple.com/library/mac/#documentation/opensource/…) .
23.
Ahh ich verstehe! Ich wusste nicht, dass es verschiedene Regex-Versionen gibt. Vielen Dank
Zulakis
6

Sie können die -s("Squeeze") Option verwenden von tr:

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

Die [:blank:]Zeichenklasse umfasst sowohl Leerzeichen als auch Tabulatoren.

Benjamin W.
quelle
-2

Ich benutze gerne den folgenden Alias ​​für bash. Bauen Sie auf dem auf, was andere geschrieben haben, und verwenden Sie sed, um mehrere Leerzeichen zu suchen und durch ein einziges zu ersetzen. Dies hilft, konsistente Schnittergebnisse zu erzielen. Am Ende durchlaufe ich noch einmal sed, um das Leerzeichen in einen Tabulator umzuwandeln, damit es einfacher zu lesen ist.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'
CNS-Sicherheitsmikrofon
quelle
Wie beantwortet dies die Frage?
Tonin