2015-02-12 16 views
9

Obecnie mam problem z danymi CSV ff.Polecenie linux sed - dodawanie ciągów na każdym końcu wiersza csv

COLUMN1,COLUMN2,COLUMN3,COLUMN4 
apple1,apple2,apple3,apple4 
banana1,banana2,banana3, 
caimito1,"caimito21 
caimito22","caimito31 
caimito32",caimito4 

To będzie wyglądać następująco:

╔══════════╦═══════════╦═══════════╦══════════╗ 
║ COLUMN1 ║ COLUMN2 ║ COLUMN3 ║ COLUMN4 ║ 
╠══════════╬═══════════╬═══════════╬══════════╬ 
║ apple1 ║ apple2 ║ apple3 ║ apple4 ║ 
║ banana1 ║ banana2 ║ banana3 ║   ║ 
║ caimito1 ║ caimito21 ║ caimito31 ║ caimito4 ║ 
║   ║ caimito22 ║ caimito32 ║   ║ 
╚══════════╩═══════════╩═══════════╩══════════╝ 

więc mój plan jest dodanie COLUMN5 i każdy wiersz to będzie mieć wartość „owoc”. wykorzystywane

Command:

sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/$/,FRUIT/g" > OUTPUT.csv 

wyjściowa:

╔══════════╦════════════════╦════════════════╦══════════╦═════════╗ 
║ COLUMN1 ║ COLUMN2  ║ COLUMN3  ║ COLUMN4 ║ COLUMN5 ║ 
╠══════════╬════════════════╬════════════════╬══════════╬═════════╣ 
║ apple1 ║ apple2   ║ apple3   ║ apple4 ║ FRUIT ║ 
║ banana1 ║ banana2  ║ banana3  ║   ║ FRUIT ║ 
║ caimito1 ║ caimito21FRUIT ║ caimito31FRUIT ║ caimito4 ║ FRUIT ║ 
║   ║ caimito22  ║ caimito32  ║   ║   ║ 
╚══════════╩════════════════╩════════════════╩══════════╩═════════╝ 

Czy istnieje jakiś sposób, aby dodać "owoc" bez wpływu "caimito" wiersz?

Próbowałem także ff. polecenie, ale nie wyszło. Dodano "," przed "$".

sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/,$/,FRUIT/g" > OUTPUT.csv 
+2

dla tabeli +1 .. –

+0

2 rdzenie sed mogą być zastąpione przez 1 z działaniem oddzielonym przez ';' jak to 'sed '1 action1; 2, $ action2 "Twój plik" – NeronLeVelu

Odpowiedz

2

Sed prawdopodobnie nie jest właściwym narzędziem do obsługi plików csv ponieważ zasady są bardziej skomplikowane niż jak może ona wyglądać (to chyba możliwe, ale takie skrypty są na ogół dość podatne na błędy, etc.). Można jednak użyć csvtools obsłużyć to:

file="FILE.csv" 
nr=$(csvtool height $file) 
ot=$(perl -e "print \"COLUMN5\\n\";for\$i(2..$nr){print \"FRUIT\\n\";}") 
echo "$ot" | csvtool paste "$file" - 

Skrypt działa w następujący sposób:

  1. Najpierw musimy obliczyć liczbę wierszy z csvtool height,
  2. Następnie wygenerować dodatkową kolumnę drukując COLUMN5 następnie n-1 razy FRUIT.
  3. Na koniec wklejamy tę zawartość po prawej stronie pliku.
2

EDYCJA: Właśnie widziałem rozwiązanie csvtool; jest to oczywiście znacznie bardziej praktyczne. Pozostawię to rozwiązanie głównie dlatego, że szkoda byłoby ukryć to i jego piękno Lovecraftian.

Cóż, tutaj jest. To jest sposób, aby to zrobić w sed:

sed ':a $!{ N; ba }; s/"[^"]*"/{&}/g; :b s/\({"[^"]*\)\n\([^"]*"}\)/\1~"~\2/g; tb; s/\n\|$/,FRUIT&/g; s/,FRUIT\(\n\|$\)/,COLUMN5\1/; :c s/\({"[^"]\)*~"~/\1\n/g; tc; s/{"\|"}/"/g' filename 

To będzie trochę jazda.Działa to w następujący sposób:

:a $!{ N; ba }       # assemble the whole file in the 
             # hold buffer 

s/"[^"]*"/{&}/g      # encase all "-enclosed fields in 
             # {"..."} to make matching the beginning 
             # and end separately possible. 

:b          # jump mark for looping 
s/\({"[^"]*\)\n\([^"]*"}\)/\1~"~\2/g # replace the first newline in all 
             # {"..."} fields with ~"~ 
tb          # loop until all were replaced 

s/\n\|$/,FRUIT&/g      # Put FRUIT at the end of all lines 
s/,FRUIT\(\n\|$\)/,COLUMN5\1/   # Replace the first ,FRUIT with ,COLUMN5 
             # The \(\n\|$\) bit is so that this 
             # works with empty files (that only 
             # have a header line) 

:c          # Jump mark for looping 
s/\({"[^"]\)*~"~/\1\n/g    # replace the first ~"~ in all {"..."} 
             # fields with a newline 
tc          # loop until all were replaced 

s/{"\|"}/"/g       # replace all {", "} markers with " 
             # again. 
1
sed '1 { 
    s/$/,COLUMN5/ 
    b 
    } 
:load 
/^\([^"]*"[^"]*"\)*[^"]*"[^"]*$/ { 
    N 
    b load 
    } 
s/$/,,,,/;s/^\(\([^,]*,\)\{4\}\).*/\1FRUIT/' YourFile 
  • dodać COLUMN5 na 1 linię niż cykl (b)
  • jeśli otwarte " jest na bieżącym buforze roboczym, załaduj nową linię i powtórzyć tę
  • dodaj 4 , domyślnie domyślnie
  • utrzymuj 4 pierwszą grupę oddzielnie przez , i dodaj FRUIT
  • (cykl)

wersja POSIX tak --posix GNU sed

na "valid" CSV (1 zgodnie ze wszystkimi argumentu oddzielnych przez ,), po prostu usunąć sekcję cykl obciążenia