замена двойных ссылок в csv

#regex #unix #csv #double-quotes

#регулярное выражение #unix #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
  

Как вы можете видеть, некоторые из них " написаны для inch и "L" во вложении " .

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

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

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

Комментарии:

1. вы пробовали s / » / ‘/g? Или вы просто хотите заменить двойные ссылки на «L» и дюймы?

2. Я просто хочу заменить дополнительные двойные ссылки. Результат должен быть доступен для чтения sqlloader, и некоторые поля могут содержать; как часть текста 🙁

Ответ №1:

Обновление (С помощью 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

Просто используя 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 сначала заменяет «в начале строки на `
  • затем оно заменяет «в конце строки другим `
  • затем оно заменяет все оставшиеся двойные кавычки " на одинарные совсем '
  • наконец, оно возвращает все " в начало и конец

Комментарии:

1. У меня нет perl для использования, а в SunOS 5.10 нет опции -o для grep : (

Ответ №2:

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

 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 одинаковы. Они заменяют все, " которые не являются прямыми соседями a ; , на один ' . Я должен сделать это дважды, чтобы иметь возможность заменить второе " из, например "L" , потому что между обоими есть только один символ " , и этому символу уже соответствует ([^;]) . Таким образом, вы также могли бы заменить "" на '' . Если у вас есть """ или """" и т.д. вы должны поместить еще одну (но только еще одну) s .

Комментарии:

1. Это выглядит почти хорошо. Заменены все дюймы. Но у меня все еще есть проблема с буквой «L», и в некоторых случаях я также обнаружил «Остаток» между разделителями полей. 🙁

2. Что вы имеете в виду под «Rest»? Можете ли вы привести пример?

3. Между дополнительными двойными ссылками есть другие слова, потому что это поле свободного текста / комментариев в исходной базе данных. Таким образом, это может быть «L» или «Rest» или «fippel-пиппель» или что-нибудь еще.

4. @Karsten: Я добавил несколько более длинную версию команды, которая теперь должна работать.

5. Спасибо, bmk. Но «L» и все остальные (например, «fippel-пиппель») по-прежнему имеют двойные ссылки. Поскольку на консоли нет ошибки, я боюсь, что ошибка в вашем sed. Я нашел эту страницу compute.cnr.berkeley.edu/cgi-bin/man-cgi?sed 1 и, похоже, доступна опция -r. Помогает ли это упростить ваше утверждение?

Ответ №3:

Для буквы «L» попробуйте это:

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

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

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

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

Комментарии:

1. Это выглядит хорошо во втором. Но в некоторых случаях я уже нашел «остаток» между разделителями полей. 🙁