Замена двойных кавычек в CSV

У меня возникла почти следующая проблема, и я не нашел решения. Это может быть моя структура файла CSV:

1223;"B630521 ("L" fixed bracket)";"2" width";"length: 5"";2;alternate A
1224;"B630522 ("L" fixed bracket)";"3" width";"length: 6"";2;alternate B

Как вы можете видеть, есть некоторые " написано для дюйма и "L" во вложении ",

Теперь я ищу сценарий оболочки UNIX, чтобы заменить " (дюйм) и "L" двойные кавычки с 2 одинарными кавычками, как в следующем примере:

sed "s/$OLD/$NEW/g" $QFILE > $TFILE && mv $TFILE $QFILE

Может кто-нибудь мне помочь?

3 ответа

Обновление (с помощью Perl это легко, так как вы получаете полные функции просмотра)

perl -pe 's/(?<!^)(?<!;)"(?!(;|$))/'"'"'/g' file

Выход

1223;"B630521 ('L' fixed bracket)";"2' width";"length: 5'";2;alternate A
1224;"B630522 ('L' fixed bracket)";"3' width";"length: 6'";2;alternate B

Используя sed, grep only

Просто используя grep, sed (а не perl, php, python и т. Д.), Не очень элегантное решение может быть:

grep -o '[^;]*' file | sed  's/"/`/; s/"$/`/; s/"/'"'"'/g; s/`/"/g' 

Вывод - для вашего входного файла он дает:

1223
"B630521 ('L' fixed bracket)"
"2' width"
"length: 5'"
2
alternate A
1224
"B630522 ('L' fixed bracket)"
"3' width"
"length: 6'"
2
alternate B
  • grep -o в основном разделяет вход по ;
  • sed вначале заменяет "в начале строки на"
  • затем он заменяет "в конце строки другим"
  • затем он заменяет все оставшиеся двойные кавычки " одним довольно '
  • наконец-то это откладывает все " в начале и в конце

Может быть, это то, что вы хотите:

sed "s/\([0-9]\)\"\([^;]\)/\1''\2/g"

Т.е. найти двойные кавычки (") после числа ([0-9]), но не следует точка с запятой ([^;]) и заменить его двумя одинарными кавычками.

Редактировать: я могу расширить свою команду (это становится довольно долго):

sed "s/\([0-9]\)\"\([^;]\)/\1''\2/g;s/\([^;]\)\"\([^;]\)/\1\'\2/g;s/\([^;]\)\"\([^;]\)/\1\'\2/g"

Поскольку вы используете SunOS, я думаю, вы не можете использовать расширенные регулярные выражения (sed -r)? Поэтому я сделал это так: первый s команда заменяет весь дюйм " с ''второй и третий s подобные. Они заменяют все " которые не являются прямым соседом ; с одним ', Я должен сделать это дважды, чтобы иметь возможность заменить второе " например "L" потому что есть только один символ между " и этот персонаж уже соответствует \([^;]\), Таким образом, вы также замените "" с '', Если у вас есть """ или же """" и т.д. Вы должны поставить еще один (но только еще один) s,

Для "L" попробуйте это:

 sed "s/\"L\"/'L'/g"

Для дюймов вы можете попробовать:

sed "s/\([0-9]\)\"\"/\1''\"/g" 

Я не уверен, что это лучший вариант, но я попробовал, и это работает. Я надеюсь, что это полезно.

Другие вопросы по тегам