Об’єднайте кілька команд sed в одному сценарії для обробки файлу CSV


34

Маючи такий файл CSV:

HEADER
"first, column"|"second "some random quotes" column"|"third ol' column"
FOOTER

і шукаємо результат типу:

HEADER
first, column|second "some random quotes" column|third ol' column

іншими словами, видаляючи "FOOTER", цитати на початку, в кінці та навколо |.

Поки цей код працює:

sed '/FOOTER/d' csv > csv1 | #remove FOOTER
sed 's/^\"//' csv1 > csv2 | #remove quote at the beginning
sed 's/\"$//' csv2 > csv3 | #remove quote at the end
sed 's/\"|\"/|/g' csv3 > csv4 #remove quotes around pipe

Як ви бачите, проблема створює 4 додаткових файли.

Ось ще одне рішення, яке має на меті не створювати зайві файли і робити те саме в одному сценарії. Це працює не дуже добре.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4

1
Оскільки у вас є котирування, ви можете мати нові рядки в полях. ви sedне будете працювати з цим, лише з спрощеним csv. Використовуйте мову програмування з бібліотекою, яка може обробляти реальні файли CSV (Python / Perl / Ruby).
Антон

Відповіді:


44

Перш за все, як показав Майкл, ви можете просто об'єднати все це в одну команду:

sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1

Я думаю, що деякі sedреалізації не впораються з цим і можуть знадобитися:

  sed -e '/^FOOTER/d' -e 's/^\"//' -e 's/\"$//' -e 's/\"|\"/|/g' csv > csv1

З цього приводу , схоже, що ваші поля визначені, |і ви просто хочете видалити "все поле, залишаючи ті, які знаходяться в полі. У цьому випадку ви можете зробити:

$ sed '/FOOTER/d; s/\(^\||\)"/\1/g; s/"\($\||\)/\1/g' csv 
HEADER
first, column|second "some random quotes" column|third ol' column

Або з GNU sed:

sed -r '/FOOTER/d; s/(^|\|)"/\1/g; s/"($|\|)/\1/g' csv 

Ви також можете використовувати Perl:

$ perl -F"|" -lane 'next if /FOOTER/; s/^"|"$// for @F; print @F' csv 
HEADER
first, column|second some random quotes column|third ol' column

13

Це також працює:

sed 's / ^ "//; s /" | "/ | / g; s /" "$ /" /'

Приклад:

$ echo '"this"|" and "ths""|" and "|" this 2"|" also "this", "thi", "and th""' | 
sed 's/^"//; s/"|"/|/g; s/""$/"/'
this| and "ths"| and | this 2| also "this", "thi", "and th"

гарненька версія

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'

1
Це не стосується нижнього колонтитулу.
terdon

3
Але це видалить останній рядок незалежно від його вмісту. Якщо немає FOOTER, він видалить потрібні дані.
terdon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.