2015-10-29 2 views
2

В моем исходном файле столбцы разделены табуляцией, а значения внутри каждого столбца разделены запятой.Bash, превращающий одиночную колонку с разделителями-запятыми в многострочную строку

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

Mary,Tom,David cat,dog 
Kevin bird,rabbit 
John cat,bird 
... 

для каждой записи во втором столбце (например, cat,dog) я хочу разделить записи в массив [кошка, собака] и поперечной печать этого против первого столбца. давая выход (только для этой линии)

Mary,Tom,David cat 
Mary,Tom,David dog 

выхода для всего файла должен быть:

Mary,Tom,David cat 
Mary,Tom,David dog 
Kevin bird 
Kevin rabbit 
John cat 
John bird 
... 

любого предложить, если я хочу использовать AWK или СЭД? Благодаря

+1

Ничего в этом вопросе не имеет никакого смысла. – 123

+0

@ 123 Мне нужно сделать файл таким образом для последующей обработки, просто интересно, будет ли более простой способ использовать bash ... или я должен привести больше примеров? – once

+0

Он имеет в виду, что вопрос не ясен, а не тот интерес, который вы должны использовать в таком формате. вывод не показывает, что объясняет ваше объяснение. что для вас разделены табуляцией и запятой?запятая и табуляция, как правило, являются разделителями столбцов (CSV-семейство). – NeronLeVelu

ответ

4

С AWK

awk '{split($2,a,",");for(i in a)print $1"\t"a[i]}' file 

расколы второй столбец на запятой, а затем для каждого разделенного значения, напечатать первый столбец и это значение

Кроме того, в СЭД

sed ':1;s/\(\([^\n]*\t\)[^\n]*\),\{1,\}/\1\n\2/;t1' file 
+1

потрясающий! Я немного потрудился за эту команду! – once

+0

действительно разделяет ($ 2, a, ",") означает разделить $ 2 на массив a? – once

+2

@once yes, и с разделителем ',' – NeronLeVelu

1

process.sh

#!/bin/bash 

while read col_one col_two; do 
    IFS=, read -a explode <<< "$col_two"; 
    for val in "${explode[@]}"; do 
    printf "%s\t%s\n" "$col_one" "$val"; 
    done; 
done <"$1"; 

с input.txt в

Mary,Tom,David cat,dog 
Kevin bird,rabbit 
John cat,bird 

выход

$ ./process.sh input.txt 
Mary,Tom,David cat 
Mary,Tom,David dog 
Kevin bird 
Kevin rabbit 
John cat 
John bird 
+0

спасибо! могу я спросить о взрыве? – once

+1

Взрыв - это просто имя массива im, читающего его (напоминает мне о взрыве php-функции, который функционально подобен этому сценарию bash) – amdixon

1

с AWK

awk '{split($2, aEl, ","); for (Eli in aEl) print $1 "\t" aEl[ Eli]}' YourFile 

с sed

sed 'H;s/.*//;x 
:cycle 
    s/\(\n\)\([^[:cntrl:]]*[[:blank:]]\{1,\}\)\([^[:cntrl:]]*\),\([^,]*\)/\1\2\3\1\2\4/;t cycle 
s/.//' YourFile 
+1

Невозможно использовать 'FS', поскольку они хотят разделить табуляции, если вы не измените FS, очевидно ... – 123

+1

хорошая точка, будет использовать вкладку непосредственно – NeronLeVelu

+0

есть еще один ответ sed ниже/(выше), он отлично работает, но я не могу понять, как ответить – once

2

Это может работать для вас (GNU СЭД):

sed -r 's/^((\S+\s+)[^,]+),/\1\n\2/;P;D' file 

процесс можно разбить на три команды: замены, печать и удаление. Замените каждый , во втором поле символом новой строки и первым полем и следующими пробелами. Затем распечатайте вверх и включите новую строку и удалите до и включите новую строку и повторите. Ключевой командой является D, которая будет повторно запускать предыдущие команды, пока пространство шаблонов не будет полностью пустым.

+0

. но я слишком глуп, чтобы понять даже с вашим объяснением – once

+0

Могу ли я спросить о S, s и P ..? – once

+0

Очень хорошее использование 'P' и' D' – NeronLeVelu

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