2016-05-15 2 views
0

Мой входной файл:Разбор данных столбцов с использованием СЭД

SMOKE_TEST_FIMS,"['a', 'b', 'c']",2015-08-01 14:00:00+0000,100 
    4.AIQM-B,,2015-04-16 12:04:21+0000,102 
    000TEST2,['1.034820'],2015-11-19 05:00:00+0000,130 

Я хочу, чтобы разобрать строку таким образом, что выходной файл будет выглядеть, как показано ниже:

Ожидаемый результат:

'SMOKE_TEST_FIMS', 'a', '2015-08-01 14:00:00+0000','100' 
'SMOKE_TEST_FIMS','b', '2015-08-01 14:00:00+0000','100' 
'SMOKE_TEST_FIMS','c', '2015-08-01 14:00:00+0000','100' 
'4.AIQM-B','','2015-04-16 12:04:21+0000','102' 
'000TEST2','1.034820','2015-11-19 05:00:00+0000','130' 

Мне удалось проанализировать данные одного столбца ['a', 'b', 'c'] до

'a' 
    'b' 
    'c' 
    sed -i "s/ *\"/'/g;s/ *[^0-9]*\('[^']*'\)\]*'*/\1/g;s/\(.\)''/\1'\n'/g;" updatebomStatement2.cql  

ответ

2

sed предназначен для простых подстановок на отдельных линиях, то есть всех. Для чего-либо более интересного вы должны использовать AWK:

$ cat tst.awk 
BEGIN { FS=",?\"?[][]\"?,?"; OFS="," } 
{ 
    if (split($2,a,/\047/)) { 
     for (j=2; j in a; j+=2) { 
      $2 = a[j] 
      prt() 
     } 
    } 
    else { 
     prt() 
    } 
} 

function prt( out) { 
    out = "\047" $0 "\047" 
    gsub(OFS,"\047,\047",out) 
    print out 
} 

$ awk -f tst.awk file 
'SMOKE_TEST_FIMS','a','2015-08-01 14:00:00+0000','100' 
'SMOKE_TEST_FIMS','b','2015-08-01 14:00:00+0000','100' 
'SMOKE_TEST_FIMS','c','2015-08-01 14:00:00+0000','100' 
'4.AIQM-B','','2015-04-16 12:04:21+0000','102' 
'000TEST2','1.034820','2015-11-19 05:00:00+0000','130' 

или здание на @karakfa's idea:

$ cat tst.awk 
BEGIN { FS="([][ \"\047])*,([][ \"\047])*"; OFS="\047,\047" } 
{ 
    for(i=2; i<=(NF-2); i++) { 
     print "\047" $1, $i, $(NF-1), $NF "\047" 
    } 
} 

$ awk -f tst.awk file 
'SMOKE_TEST_FIMS','a','2015-08-01 14:00:00+0000','100' 
'SMOKE_TEST_FIMS','b','2015-08-01 14:00:00+0000','100' 
'SMOKE_TEST_FIMS','c','2015-08-01 14:00:00+0000','100' 
'4.AIQM-B','','2015-04-16 12:04:21+0000','102' 
'000TEST2','1.034820','2015-11-19 05:00:00+0000','130' 
+1

Благодаря Ed .. он работал – saurav

+0

сэр над сценарием работает хорошо , просто у меня есть одно сомнение, могу ли я написать tst.awk внутри моего .sh-файла? – saurav

+0

Да 'awk 'script' file'. человек awk. Кстати, английское слово «вопрос» не «сомнение» - «сомнение» подразумевает, что вы не верите чему-то. –

3

Если вы в порядке с Gnu раствором AWK вот такой скрипт:

script.awk

BEGIN { FPAT = "(\"[^\"]+\")|(\\[[^\\]]+\\])|([^,]*)" 
     OFS = "," 
     } 

{ if ($2~/\[[^\]]+/) { 
    # sanitize input: strip ", [, ]: 
    gsub(/[\[\]\"]/, "", $2) 

    # split at "," into parts: and print them 
    split($2, parts, ",") 
    for(ind in parts) { 
     # further normalize input 
     gsub(/^ ?'/, "", parts[ind]) 
     gsub(/'$/, "", parts[ind]) 
     tmp=sprintf("'%s','%s','%s','%s'", $1, parts[ind], $3, $4) 
     print tmp 
    } 
    } 
    else { 
     tmp=sprintf("'%s','%s','%s','%s'", $1, $2, $3, $4) 
     print tmp 
    } 
} 

Выполнить это так: awk -f script.awk yourfile.

Imho gnu awk с его функцией FPAT и его контрольными инструкциями гораздо лучше подходит для ваших требований, чем sed.

В первой строке с FPAT описывается, что махирует поле на вашем входе. Это либо

  • что-то в двойных кавычках "
  • что-то внутри скобок [ ... ]
  • или что-то через запятую

Условный оператор совпадает скобка случай, который должен быть разделен на несколько строк ,

1

альтернатива Hacky awk

$ awk -F, -v OFS=, -v q="'" '{gsub(/[ "\]\[]/, ""); 
           for(i=2;i <=NF-2; i++) 
           {$i=$i?$i:q q; 
            print q $1 q, $i, q $(NF-1) q,q $NF q}}' file 

'SMOKE_TEST_FIMS','a','2015-08-0114:00:00+0000','100' 
'SMOKE_TEST_FIMS','b','2015-08-0114:00:00+0000','100' 
'SMOKE_TEST_FIMS','c','2015-08-0114:00:00+0000','100' 
'4.AIQM-B','','2015-04-1612:04:21+0000','102' 
'000TEST2','1.034820','2015-11-1905:00:00+0000','130' 
+0

Не все awks будут принимать квадратные скобки в выражении скобки, избегая их (может быть, gawk-only, idk) - портативно вам нужно просто поместить их в начало выражения скобки, '[] ["] '. Также' $ i = $ i? $ i: qq' может генерировать синтаксическую ошибку для некоторых awks из-за несферизированного тернарного выражения, и он будет терпеть неудачу для полей, которые численно оцениваются до нуля, используйте '$ i = ($ i ==" " ? qq: "") '. Вместо этого мне нравится идея, но ее можно немного упростить, если вы включили' \ 047' в выражение для скобок, так как тогда поле EVERY добавляет окружающие кавычки. –

+0

Я отредактировал [мой ответ] (http://stackoverflow.com/a/37255830/1745001), чтобы в конце показать, что я получаю с моим комментарием выше о том, как его можно упростить. Если вы хотите отредактировать свой ответ, включите его, а затем удалите его у меня. –

+1

спасибо за комментарии, '\ 047' - это хорошая идея для упрощения цитирования. – karakfa

Смежные вопросы