Jak zastąpić wiele spacji jedną kartą

27

Mam kilka plików tekstowych, które zawierają niektóre kolumny oddzielone różną liczbą spacji, ale zamiast tego potrzebuję jednej pojedynczej karty jako separatora. Czy można to zrobić w Bash?

nieznany użytkownik
źródło
Dzięki za wspaniały wkład, ale mam kilka pojedynczych spacji w kolumnie, więc muszę unikać tabulacji pojedynczej spacji. przepraszam za to, informacja.
user_unknown

Odpowiedzi:

31

Aby przekonwertować sekwencje więcej niż jednej spacji na tabulację, ale pozostaw pojedyncze spacje w spokoju :

sed 's/ \+ /\t/g' inputfile > outputfile

Aby to zrobić dla wielu plików:

for inputfile in *
do
    sed 's/ \+ /\t/g' "$inputfile" > tmpfile && mv tmpfile "$inputfile"
done

lub

for inputfile in *
do
    sed -i.bak 's/ \+ /\t/g' "$inputfile"
done

lub

find . -type f -exec sed -i.bak 's/ \+ /\t/g' {} \;
Wstrzymano do odwołania.
źródło
sed: -e expression #1, char 1: unknown command: `.'
Aaron Franke
@AaronFranke: Jakiego polecenia próbowałeś? Żaden z przykładów w mojej odpowiedzi nie powinien powodować tego błędu.
Wstrzymano do odwołania.
Przepraszam, powinienem był to wyjaśnić. Ten findna dole.
Aaron Franke
@AaronFranke: GNU sednie lubi mieć spacji przed rozszerzeniem kopii zapasowej. Zredagowałem swoją odpowiedź. Dziękuję za raport.
Wstrzymano do odwołania.
7

Jeśli twoja postać ma wiele kart, możesz także użyć tr -s:

-s, --squeeze-repeats   replace each input sequence of a repeated character
                        that is listed in SET1 with a single occurrence

Na przykład:

my_file.txt | tr -s " "

Wszystkie białe spacje staną się jednym.

użytkownik597119
źródło
O to nie prosi OP.
RonJohn
5

Możesz użyć, sedaby zastąpić wiele spacji tabulatorem:

Przykład zamiany jednego lub więcej spacji na jedną kartę:

cat spaced-file | sed 's/ \+/\t/g' > tabbed-file
IvanGoneKrazy
źródło
OP stwierdził, że liczba spacji jest zmienna , więc nie sądzę, aby to rozwiązanie działało.
Mikel
@Mikel. Ups Dzięki za zwrócenie na to uwagi. Zmodyfikowałem post, aby umożliwić dopasowanie do zmiennych przestrzeni.
IvanGoneKrazy
Najbardziej przydatna odpowiedź tutaj.
Luís de Sousa
3

Najłatwiejsza odpowiedź, używając tylko bash:

while read -r col1 col2 col3 ...; do
    echo -e "$col1\t$col2\t$col3..."
done <file

Jeśli istnieje zmienna liczba kolumn, można to zrobić, ale to będzie działać tylko na bashnie sh:

while read -r -a cols; do
    (
        IFS=$'\t'
        echo "${cols[*]}"
    )
done <file

na przykład

while read -r -a cols; do
    (
        IFS=$'\t'
        echo "${cols[*]}"
    )
done <<EOF
a b   c
d   e    f
  g h i
EOF

produkuje:

a   b   c
d   e   f
g   h   i

(między nimi jest zakładka, ale trudno ją zobaczyć, kiedy ją tu wkleję)

Możesz to również zrobić za pomocą sedlub tr, ale zauważ, że obsługa pustych miejsc na początku daje różne wyniki.

sed:

$ sed 's/  */\t/g' << EOF
a b   c
d   e    f
  g h i
EOF
a       b       c
d       e       f
        g       h       i

tr:

$ tr -s ' ' '\t' <<EOF
a b   c
d   e    f
  g h i
EOF
a       b       c
d       e       f
        g       h       i
Mikel
źródło
2

perl -p -i -e 's/\s+/\t/g' *.txt

RedGrittyBrick
źródło
2

Wypróbuj następujący skrypt SED:

 sed 's/  */<TAB>/g' <spaces-file > tabs-file

Gdzie <TAB> naciska klawisz TAB.

mdpc
źródło
0

To bardzo proste rozwiązanie:

    sed -E 's/\s+/\t/g' your_file > new_file

sed zasadniczo działa w ten sposób (sed 's / old_pattern / new_pattern / g'). W tym przypadku stary wzorzec to „\ s +”, co oznacza znalezienie spacji raz lub więcej razy „+” i ukośnik odwrotny „\”, aby zinterpretować to jako wyrażenie regularne.
Nowym wzorcem jest tab „\ t”, który jest zapisany w formacie wyrażeń regularnych, a „g” oznacza zastąpienie wszystkich wierszy „globalnie”.

Waleed Omer
źródło
1
Witam i witam u administratora. Powinieneś poświęcić czas na wyjaśnienie swojego rozwiązania. Dla kogoś, kto nie zna systemów * nix, sed i wyrażeń regularnych, wygląda to na stos dziwnych znaków.
Mogget