Преобразовать часть строки в столбцы

У меня есть файл с входом:

rownum,identifier,items_in_list
1,"ABC",{(123),(345),(69),(95),(90),(83),(3A)}

с ожидаемым результатом как:

rownum,identifier,items_in_list
1,"ABC",123
1,"ABC",345
1,"ABC",69
1,"ABC",95
1,"ABC",90
1,"ABC",83
1,"ABC",3A

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

Мой код:

echo "1,"ABC",{(123),(345),(69),(95),(90),(83),(3A)}" | awk -vRS="{" 'NF'

но это превращается в:

1,ABC,
(123),(345),(69),(95),(90),(83),(3A)}

Обновить:

Все ваши команды работают нормально, но из-за одного небольшого сбоя, извините за то, что я новичок, я могу проголосовать только за одну.

Благодарю вас! но у меня возникают проблемы, если строки не имеют нескольких номеров и имеют только одно.. например, в этом формате:

вход

1,33262,"ABC",{(64)} 
1,33263,"ABC",{(66),(57)}

Фактический выход:

1,33262,SOME_FIELD_NAME 
1,33262,64 
1,33263,SOME_FIELD_NAME 
1,33262,65,66 

Требуемый выход:

1,33262,SOME_FIELD_NAME,64 
1,33263,SOME_FIELD_NAME,65
1,33263,SOME_FIELD_NAME,66

Обновить:

"Фактический вывод" кода, предложенного Йотном: awk -F, '{a=$1","$2;gsub(/[{()}]/,""); для (i=3;i<=NF;i++) распечатать файл ","$i}'.

Извините, мой ввод иногда имеет 2 ведущих поля и 3-10 ведущих полей иногда, но строка, которую мы хотим преобразовать в столбец, всегда начинается с '{', отдельные числа заключены в '()', а конец строки равен обозначается '}'. Код Джотна прекрасно работает для 2 ведущих полей, но не работает для 3 ведущих полей. Может кто-нибудь предложить общий способ разбора полей?

4 ответа

Решение

Вот один из способов awk

awk -F, '{a=$1","$2;gsub(/[{()}]/,"");for (i=3;i<=NF;i++) print a","$i}' file
1,"ABC",123
1,"ABC",345
1,"ABC",69
1,"ABC",95
1,"ABC",90
1,"ABC",83
1,"ABC",3A

С помощью RS

awk -vRS=, '{gsub(/[{()}]/,"")} NR==1 {a=$1;next} NR==2 {a=a","$1;next} {print a","$1}' file
1,"ABC",123
1,"ABC",345
1,"ABC",69
1,"ABC",95
1,"ABC",90
1,"ABC",83
1,"ABC",3A

Если вы все еще ищете решение Python:

input = '1,"ABC",{(123),(345),(69),(95),(90),(83),(3A)}'
for extra_char in '{}()"':
    input = input.replace(extra_char, '')
input_elems = input.split(',')
rownum, identifier = input_elems[0:2]
for item in input_elems[2:]:
    print rownum, identifier, item
awk -F, '{gsub(/)./,ORS); gsub(/(^[^(]+)?[(]/,$1 OFS $2 OFS); printf "%s",$0}' file
1,"ABC",123
1,"ABC",345
1,"ABC",69
1,"ABC",95
1,"ABC",90
1,"ABC",83
1,"ABC",3A

Основанное на Python решение:

import csv
import re

data = ['rownum,identifier,items_in_list',
        '1,"ABC",{(123),(345),(69),(95),(90),(83),(3A)}']

reader = csv.reader(data)  # change data to open(filename, 'rb')
pat = r'{*\(([0-9a-fA-F]+)\)}*'
next(reader)
for row in reader:
    for elem in row[2:]:
        mat = re.search(pat, elem).group(1)
        print(','.join([row[0], '"{}"'.format(row[1]), mat]))

Выход:

1,"ABC",123
1,"ABC",345
1,"ABC",69
1,"ABC",95
1,"ABC",90
1,"ABC",83
1,"ABC",3A
Другие вопросы по тегам