Разделить CSV-файл в соответствии со значением в столбце, но сохранить только 1 столбец и сохранить как TXT

#csv #awk

#csv #awk

Вопрос:

У меня есть электронная таблица с двумя столбцами (сохраненная в формате CSV), которая выглядит следующим образом:

 COLUMN 1,COLUMN 2
innovation,3-Entrepreneurship
countless,
innocent,2-Police
toilet handle,2-Bathroom
née dresses,3-Companies
odorless,2-Sense of Smell
old ideas,3-Entrepreneurship
new income streams,3-Entrepreneurship
Zoë’s food store,3-Companies
many,
crime,2-Police
bath room,2-Bathroom
ring,
móvíl résumés,3-Companies
musty smell,2-Sense of Smell
good publicity guru,3-Entrepreneurship
Señor,3-Companies
  

Полная электронная таблица состоит из 6000 строк (сохранена в формате CSV, с запятыми, используемыми для разделения двух столбцов). В нем больше категорий, чем в столбце 2, которые перечислены здесь.

Как показано, некоторые записи в столбце 1 состоят из двух или трех слов, разделенных пробелом. Они также используют апострофы и символы с ударением (они отображаются в нескольких категориях, а не только в категории с названием 3-Companies ).

Вы можете скачать образец полной таблицы здесь.

Я хотел бы разделить CSV-файл, чтобы разделить TXT-файлы по значениям в столбце 2. Отдельные файлы больше не будут электронной таблицей, а просто списком слов.

Например. после разделения

В файле 3-Entrepreneurship.txt

 innovation
old ideas
new income streams
good publicity guru
  

В файле 2-Bathroom.txt

 toilet handle
bath room
  

В файле 2-Police.txt

 innocent
crime
  

В файле 2-Смысл Smell.txt

 odorless
musty smell
  

В файле 3-Companies.txt

 née dresses
Zoë’s food store
móvíl résumés
Señor
  

Это всего лишь пример. Полный файл имеет более 5 категорий (в столбце 2), поэтому после разделения будет более 5 файлов.


Вот мой код на данный момент:

 awk -F "," '{print $0 >> ($2 ".txt"); close($2 ".txt")}' test.csv
  

Это работает, но есть несколько проблем:

  1. Имена файлов выводятся с вопросительными знаками в конце. Например. 2-Police?.txt 3-Entrepreneurship?.txt

  2. Файлы распечатываются с двумя столбцами.

Например, внутри 3-Entrepreneurship.txt в нем содержатся следующие данные:

 innovation  3-Entrepreneurship
ideas       3-Entrepreneurship
income      3-Entrepreneurship
publicity   3-Entrepreneurship
  

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

1. Вы должны напечатать первое поле, а не всю строку: print $1 >> . Ваша вторая проблема, вероятно, связана с окончанием строки DOS (» r n») во входном файле. Возможно, вы захотите вызвать awk с awk -v RS='rn'

2. Я не знаю. Ваш вызов awk отлично работает на моем окне. Но будьте осторожны, что строки только с одним полем будут собраны в файл с именем .csv .

3. У вас есть опечатки в командной строке. Так и должно было быть awk -v RS='rn' -v ORS='r'

4. @M.NejatAydin использование более 1 символа в RS является неопределенным поведением для POSIX, поэтому настройка RS='rn' будет делать то, что вы хотите в GNU awk и, возможно, некоторых других, но в других все равно будет вести себя так, как если бы вы написали, RS='r' вероятно, поэтому OP видит пустые строки перед каждой записью, это n то, что должно было быть в конце каждой строки, теперь помещается в начало следующей строки.

5. @big_smile пишет I am using Mac OS 10.14.6 if that makes a difference да, это так. Awk по умолчанию в macOS — это BSD awk, и он ожидает только значения RS с одним символом и обрезает любые RS с несколькими символами до первого символа, и поэтому будет обрабатываться RS='rn' так, как если бы вы написали RS='r' . Если вы установите GNU awk вместо этого, вы сможете использовать RS с несколькими символами и массу других очень полезных расширений.

Ответ №1:

 tail -n  2 file |
sort -t',' -k2 |
awk -F',' '$2~/^[[:space:]]*$/{next} {sub(/r$/,"")} $2!=prev{close(out); out=$2".txt"; prev=$2} {print $1 > out}'
  

Сначала мы сортируем данные для повышения эффективности, чтобы awk не приходилось открывать / закрывать файлы построчно, а вместо этого делать это только один раз за уникальное значение в 2 доллара.

Вот работающий скрипт:

 $ ls
file

$ cat file
COLUMN 1,COLUMN 2
innovation,3-Entrepreneurship
countless,
innocent,2-Police
toilet handle,2-Bathroom
née dresses,3-Companies
odorless,2-Sense of Smell
old ideas,3-Entrepreneurship
new income streams,3-Entrepreneurship
Zoë’s food store,3-Companies
many,
crime,2-Police
bath room,2-Bathroom
ring,
móvíl résumés,3-Companies
musty smell,2-Sense of Smell
good publicity guru,3-Entrepreneurship
Señor,3-Companies
  

.

 $ tail -n  2 file | sort -t',' -k2 | awk -F',' '$2~/^[[:space:]]*$/{next} {sub(/r$/,"")} $2!=prev{close(out); out=$2".txt"; prev=$2} {print $1 > out}'
  

.

 $ ls
 2-Bathroom.txt   2-Police.txt  '2-Sense of Smell.txt'   3-Companies.txt   3-Entrepreneurship.txt   file

$ head -n 50 *.txt
==> 2-Bathroom.txt <==
bath room
toilet handle

==> 2-Police.txt <==
crime
innocent

==> 2-Sense of Smell.txt <==
musty smell
odorless

==> 3-Companies.txt <==
móvíl résumés
née dresses
Señor
Zoë’s food store

==> 3-Entrepreneurship.txt <==
good publicity guru
innovation
new income streams
old ideas
  

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

1. Спасибо, я обновил вступительный пост. Спасибо за вашу помощь и терпение!

2. Спасибо, это здорово! Я заметил, что он добавляет пустую строку в конец каждого файла. Есть ли какой-либо способ избежать этого?

3. Нет, он этого не делает, как вы можете видеть в head выводе в моем ответе.

Ответ №2:

Вы очень близки.

Во-первых, кажется, что слова без значения в столбце 2 не должны записываться в файл. Если это так, добавьте тест к своему действию. Тест может быть просто, $2 который пропустит действие внутри поля, { ... } если $2 оно пустое.

Во-вторых, если вам нужно только слово, напишите в файл только столбец 1, а не всю строку в $0

В вашем примере, который не имеет , разделителей, вы можете сделать:

 awk '$2 {print $1 >> ($2 ".txt"); close($2 ".txt")}' file
  

Обязательно удалите .txt файлы или запустите в пустом каталоге, поскольку при этом будут добавлены файлы, если они уже существуют.

Выдает:

 2-Bathroom.txt:
toilet
bath

2-Police.txt:
innocent
crime

2-Sense.txt:
odorless
musty

3-Entrepreneurship.txt:
innovation
ideas
income
publicity
  

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

1. Этот тип работает, за исключением того, что ,3-Entrepreneurship.txt разделяется на два файла. Первый файл содержит «инновации», «идеи» и «доход», в то время как второй файл ( ,3-Entrepreneurship?.txt ) содержит только «публичность». Кроме того, перед именами всех файлов ставится запятая.