Замена двойных кавычек в 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"
Я не уверен, что это лучший вариант, но я попробовал, и это работает. Я надеюсь, что это полезно.