2013-12-16 3 views
2

У меня есть много данных, которые я пытаюсь разбить в CSV. Мои исходные данные имеют следующий формат:Сплит данных с помощью sed или awk

* USER 'field1' '[email protected]' 'field3' 
* USER 'field1' '[email protected]' 'field3' 
* USER 'field1' '[email protected]' 'field3' 

И вот что я пытаюсь получить в качестве вывода:

field1;[email protected];field3 
field1;[email protected];field3 
field1;[email protected];field3 

Правила:

  1. * USER в начало строки должен быть явно лишен;
  2. field1 и field3 может быть адресом электронной почты или может содержать ';
  3. field1 может быть пустым ''
  4. второе поле всегда является адресом электронной почты;
  5. каждое поле имеет ' в начале и конце самого поля.

Моя идея состояла в том, чтобы лишить * USER (sed -e 's/^* USER //' может стать отправной точкой), то «найти» почту в «центре» поле, а затем поймать левую сторону и правую сторону на Варс. Последняя вещь должна состоять в том, чтобы разбить начало и конец ' на vars. К сожалению, у меня нет знаний sed или awk на этом уровне. Любые идеи о том, как достичь этого?


Вот пример

* USER '' '[email protected]' 'CORDINI ALBERTO' 
* USER 'moglie delmonte daniele' '[email protected]' 'Anna Borghi' 
* USER '' '[email protected]' 'CRAVERO ANNA MARIA' 
* USER '' '[email protected]' 'D'AGOSTINO PATRIZIA' 
* USER '' '[email protected]' 'DE PRA' PIERO' 
* USER '' '[email protected]' 'D'INGEO VIVIANA' 
+1

Если вы можете добавить небольшой образец, содержащие случаи/правила, которые вы добавили в свой пост, это, безусловно, будет легче помочь. – Rubens

+0

Я разместил пример ниже –

+0

, почему использовать '' 'а не' '' для того, чтобы окружать имена, которые могут содержать '' '? ... он задает проблемы. –

ответ

5

Update: Вы можете использовать эту AWK для предоставленному ввода:

awk -F " '" '{gsub(/^ +| +$/, "", $3); 
       s=sprintf("%s;%s;%s;", $2,$3,$4); gsub(/'"'"';/, ";", s); print s}' file 
;[email protected];CORDINI ALBERTO; 
moglie delmonte daniele;[email protected];Anna Borghi; 
;[email protected];CRAVERO ANNA MARIA; 
;[email protected];D'AGOSTINO PATRIZIA; 
;[email protected];DE PRA' PIERO; 
;[email protected];D'INGEO VIVIANA; 
+0

не работает должным образом. Посмотрите пример ниже –

+0

ok let я попробую с вашей датой примера и вернусь. – anubhava

+0

обратите внимание на мое «правило 2» ...: D спасибо! –

4

Просто:

$ awk '{print $2,$4,$6}' FS="'" OFS=";" file 
field1;[email protected];field3 
field1;[email protected];field3 
field1;[email protected];field3 
+2

Ну. Это работает с небольшим изменением. 'FS = "\ 047" '. Некоторые системы этого не принимают. По крайней мере, мой блок Solaris – Vijay

+0

Мне нравится то, что вы используете устаревший и завершающий апостроф как FS. Это работает до тех пор, пока пользователь O'Hara не использует свое настоящее имя (Google xkcd Johnny Tables для предостережения). Все еще получает мой голос ... – Floris

+0

он не работает должным образом. смотрите пример ниже –

0

Вы могли бы использовать sed и aw k, и это будет работать, но, как и вы, я не использую те, которые достаточно часто запоминаются (и я нахожу их неуклюжими). Если вам нужно решение, которое вы можете поместить в скрипт для запуска все время, то как насчет решения Руби, я использую регулярное выражение, но вы не должны:

образца-data.txt

* USER 'field1' '[email protected]' 'field3' 
* USER 'field1' '[email protected]' 'field3' 
* USER 'field1' '[email protected]' 'field3' 

parse.rb

#!/usr/bin/env ruby 

$stdin.each_line do |e| 
    matches = e.match /\*\ USER\ '([\w]*)'\ '([\w\@\.]*)'\ '([\w]*)'/ 
    if matches != nil 
     puts "#{matches[1]};#{matches[2]};#{matches[3]}" 
    end 
end 

Из терминала/командной строки:

cat sample-data.txt | ruby parse.rb 

пс Для меня, если это разовая проблема, я бы использовал Notepad ++ в Windows. Я бы открыл файл, затем запустил макрос и выполнил макрос в конце файла.

+0

извините, но я не могу установить ruby ​​на этом сервере ... –

+0

Нет проблем! Просто хотел дать вам альтернативу. – buddyw

0
sed "s/²/²S/g;s/\\'/²q/g;s/\*[[:blank:]]USER[[:blank:]]\{1,\}'\([^']*\)'[[:blank:]]*'\([^']*\)'[[:blank:]]*'\(.*\)'[[:blank:]]*$/\1;\2;\3/;s/²q/\\'/g;s/²S/²/g" YourFile.csv 

Предполагая, что нет поля 1 с ' внутри, что/не экранируются

0

sed пример, он опирается на тот факт, что существуют единичные пробелы между кавычки разделителями полей. Если это не так, то это требует модификации, чтобы быть более «гибким».

Чтобы избежать прокрутки кода, которая является своего рода уродливым опытом, я бы поместил один вкладыш в файл. -r делает это с использованием расширенного регулярного выражения (избегая цитирования () s). Одинарные кавычки внутри field1 и field3 сохраняется при регулярных выражениях жадности (ест все, в том числе котировки до прошлого цитаты :)

sed -r -f s.sed samp.csv 

s.sed:

s/\* USER '(.*)' '([^']*)' '(.*)'/\1;\2;\3/ 
Смежные вопросы