sed zastąp wszystkie tabulatory i spacje pojedynczym spacją

23

Mam ciąg podobny do następującego:

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

teraz chcę zastąpić wszystkie tabulatory / spacje między rekordami tylko jedną spacją, aby z łatwością móc z niej korzystać cut -d " "

Próbowałem następujące:

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

i różne odmiany, ale nie mogłem go uruchomić. Jakieś pomysły?

Zulakis
źródło
Spróbuj: sed -r -e "s / [\ t \] + / / g"
RJS
Czy twoja opcja cutwsparcia -w?
Kondybas,

Odpowiedzi:

40

Posługiwać się sed -e "s/[[:space:]]\+/ /g"

Oto wyjaśnienie:

[   # 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).

W celu wymiany chcesz wstawić tylko spację. [:space:]nie będzie tam działał, ponieważ jest to skrót od klasy postaci, a silnik regex nie wiedziałby, jaką postać tam umieścić.

+Musi być uciekł w regex ponieważ z SED regex silnika +jest normalną postać natomiast \+jest Metaznak dla „jednej lub więcej”. Na stronie 86 Mastering Regular Expressions Jeffrey Friedl wspomina w przypisie, że ed i grep używają nawiasów ucieczkowych, ponieważ „Ken Thompson uważał, że wyrażenia regularne będą używane głównie do pracy z kodem C, gdzie potrzeba dopasowania surowych nawiasów byłaby bardziej powszechna niż odwracanie . ” Zakładam, że tak samo czuł się ze znakiem plus, stąd potrzeba ucieczki przed nim, aby użyć go jako metaznaku. Łatwo się o to potknąć.

W sed musisz uciec +, ?, |, (, i ). lub użyj -r, aby użyć rozszerzonego wyrażenia regularnego (wtedy wygląda jak sed -r -e "s/[[:space:]]\+/ /g"lubsed -re "s/[[:space:]]\+/ /g"

Rozgwiazda
źródło
Czy to też usuwa karty? Czy możesz wyjaśnić, dlaczego używasz \+zamiast po prostu +?
Zulakis,
Okej rozumiem. [[: spacja:]] jest równa [\ t \ r \ n \ v \ f]. Ale czy możesz wyjaśnić, dlaczego używasz\+
Zulakis,
3
[[: space:]] jest równoważne z „\ s”, więc krótsza wersja to „s / \ s \ + / / g”
3molo
2
Podstawowe wyrażenia regularne używają ukośnika odwrotnego przed znakiem plus, gdy oznaczają „jeden lub więcej poprzedniego znaku lub grupy”, źródło developer.apple.com/library/mac/#documentation/opensource/… .
3molo
Ach, rozumiem! Nie wiedziałem, że istnieją różne wersje wyrażeń regularnych. Dzięki
Zulakis,
6

Możesz użyć opcji -s(„ściśnij”) 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

[:blank:]Klasa znaków obejmuje zarówno przestrzenie i kart.

Benjamin W.
źródło
-2

Lubię używać następującego aliasu do bash. Opierając się na tym, co napisali inni, użyj sed, aby wyszukać i zastąpić wiele spacji jedną spacją. Pomaga to uzyskać spójne wyniki cięcia. Na koniec uruchamiam go jeszcze raz, aby zmienić spację na tabulator, aby ułatwić czytanie.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'
Zabezpieczenia CNS zsynchronizowane
źródło
Jak to odpowiada na pytanie?
Tonin,