Strona 1 z 2

[+] doklejanie tekstu do końca pliku - bash

: 05 października 2010, 17:59
autor: Skibbi
Witam,
Mam do obrobienia kilka plików csv (100-200MB każdy). Muszę przeprowadzić na nich kilka różnych operacji. Utknąłem w jednym punkcie niestety, więc liczę na pomoc bardziej zaawansowanych użytkowników konsoli. Pliki csv zawierają n kolumn, jedna z nich jest w postaci:

Kod: Zaznacz cały

ABC_DE_1234567890_1_1234
Kolumna ta znajduje się na początku, a ja bym chciał wartość z tej kolumny dokleić na koniec pliku:

Kod: Zaznacz cały

kol_A,kol_B,MOJA_KOLUMNA,kol_C,kol_D,MOJA_KOLUMNA_KOPIA
Da się to jakoś zrobić? Póki co mi się udało tę kolumnę odseparować za pomocą regexpa do oddzielnego pliku, ale jak poszczególne linie z tego pliku dokleić do mojego csv?

: 05 października 2010, 18:31
autor: lessmian2
Sprecyzuj. Chodzi Ci o koniec pliku czy linii? Wytrwale piszesz o końcu pliku, a z przykładu wychodzi, że chcesz coś dołożyć na końcu każdej linii z pliku.

Kod: Zaznacz cały

sed -i 's/\(.*,.*\)\(,.*\)\(,.*,.*\)/\1\2\3\2/' plik.csv
To powyżej zrobi coś takiego z każdą linią w pliku:

Kod: Zaznacz cały

# echo 'kol_A,kol_B,MOJA_KOLUMNA,kol_C,kol_D' | sed 's/\(.*,.*\)\(,.*\)\(,.*,.*\)/\1\2\3\2/'
kol_A,kol_B,MOJA_KOLUMNA,kol_C,kol_D,MOJA_KOLUMNA

: 05 października 2010, 19:32
autor: Skibbi
Tak, rzeczywiście chodziło mi o koniec linii w pliku. Kombinowałem z sedem, ale właśnie brakuje kropki nad i. Z tym, że ja kolumn w pliku mam ponad 100, więc ten sed chyba odpada :(

: 05 października 2010, 19:52
autor: lessmian2
E tam. Wszystko się da. Wklej przykładową linię i coś wymyślimy :)

: 05 października 2010, 22:10
autor: Skibbi
Za dużo kolumn by się bawić w kopiuj/wklej. Ale postaram się dać dokładny przykład. Mój plik źródłowy:

Kod: Zaznacz cały

ABC,23-DEF,,45A,<dużo innych kolumn>,[B]ABC_DE_1234567890_1_1234[/B],<dużo innych kolumn>,123ABC,DEFG
ABC,233-AAD,XXDS3984039,45BBGA,<dużo innych kolumn>,[B]XYZ_DE_1234567890_0_6666[/B],<dużo innych kolumn>,3ABC,DEF
Co bym chciał uzyskać:

Kod: Zaznacz cały

ABC,23-DEF,,45A,<dużo innych kolumn>,[B]ABC_DE_1234567890_1_1234[/B],<dużo innych kolumn>,123ABC,DEFG,[color=red][B]ABC_DE_1234567890_1_1234[/B][/color]
 ABC,233-AAD,XXDS3984039,45BBGA,<dużo innych kolumn>,[B]XYZ_DE_1234567890_0_6666[/B],<dużo innych kolumn>,3ABC,DEF,[color=red][B]XYZ_DE_1234567890_0_6666[/B][/color]
Jak widać występują tutaj dwa problemy: kolumna, która mnie interesuje jest w środku (a tych kolumn jest ponad 100 i ich liczba jest różna w zależności od pliku csv) oraz długość wierszy w pliku jest zmienna, czasami kolumna jest pusta więc są dwa przecinki itp.

: 05 października 2010, 22:33
autor: lessmian2
Sprawdź coś takiego:

Kod: Zaznacz cały

# echo 'kol_A,kol_B,MOJA_KOLUMNA,kol_C,kol_D' | perl -lne 'chomp;split",";print join(",",(@_,$_[2]))'
kol_A,kol_B,MOJA_KOLUMNA,kol_C,kol_D,MOJA_KOLUMNA

Kod: Zaznacz cały

perl -i -lne 'chomp;split",";print join(",",(@_,$_[2]))' plik.csv
W $_[2] wstawiasz numer kolumny, liczony od zera.

: 06 października 2010, 23:26
autor: turox
Korzystając z samego tylko basha:

Kod: Zaznacz cały

#!/bin/bash

while read ln ; do
IFS=','
declare -a linia=($ln)
echo -ne "${linia
[*]},${linia[2]}\n"
done < plik.csv
Dokleja na końcu każdej linii zawartość trzeciej kolumny.

: 07 października 2010, 10:29
autor: Skibbi
Dziękuję za basha, zadziałał perfekcyjnie. Co prawda musiałem policzyć która to kolumna musi być doklejona na końcu (wyszło że 186 :P), ale się udało.
A tak się zastanawiam: da się jakoś z pliku wejściowego zrobić dwa pliki wyjściowe w tej pętli? Plik A = oryginalny plik + doklejona kolumna. Plik B = kolumna 1, kolumna 4, kolumna 6. Ale to tak już poza konkursem :)
Jeszcze raz dziękuję za pomoc!

: 07 października 2010, 15:56
autor: turox
Przecież to banał

Kod: Zaznacz cały

#!/bin/bash

IFS=','
> plikA.csv
> plikB.csv

while read ln ; do
  declare -a linia=($ln)
  echo "${linia
[*]},${linia[2]}" >> plikA.csv
  echo "${linia[0]},${linia[3]},${linia[5]}" >> plikB.csv
done < plik.csv

: 07 października 2010, 18:11
autor: lessmian2
Tak w ramach OT. Nie rozumiem czemu tak się boicie tego perla. Zamiast skorzystać z ładnego i krótkiego jednolinijkowca, rozdmuchujecie problem do całkiem sporego, w porównaniu do tego samego kodu w perlu, skryptu w bashu ;) Wszak perl został stworzony do przetwarzania tekstów (choć zastosowań ma o wiele więcej), więc używajmy go, nie gryzie ;)