awk как разделить в разных файлах все строки с одинаковым содержимым в заданном столбце

awk как разделить в разных файлах все строки с одинаковым содержимым в заданном столбце

У меня есть большой CSV-файл (Test.csv), который выглядит так:

1,2,3,A,5
1,2,3,B,5
1,2,3,E,5
1,2,3,D,5
1,2,3,Z,5
1,2,3,B,5

Я хочу напечатать строки, в которых 4-й столбец имеет одинаковое содержимое в разных файлах. На самом деле, мне нужно объединить эти строки, которые имеют одинаковое содержимое, в новый файл csv или txt, названный как содержимое 4-го столбца. Например:

Выход:

Файл А

1,2,3,A,5
1,2,3,A,5
1,2,3,A,5

Файл Б

1,2,3,B,5
1,2,3,B,5

Поскольку входной файл большой, я понятия не имею, сколько различных шаблонов в этом 4-м столбце. Столбец 4 содержит только слова, а другие столбцы содержат слова и/или числа.

Поскольку у меня нет опыта, я исследовал похожие вопросы и даже попробовал следующий код:

awk 'NR==FNR{a[$4]=NR; next} $NF in a {print > "outfile" a[$NF]}' Test.csv

но ничего не получилось. Может кто-нибудь помочь, пожалуйста? Заранее спасибо.

решение1

Это будет эффективно работать при использовании сортировки POSIX и любого awk в любой оболочке на любой машине UNIX:

$ sort -t, -k4,4 test.csv |
    awk -F, '$4!=prev{close(out); out="File"$4; prev=$4} {print > out}'

$ head -n 20 File*
==> FileA <==
1,2,3,A,5

==> FileB <==
1,2,3,B,5
1,2,3,B,5

==> FileD <==
1,2,3,D,5

==> FileE <==
1,2,3,E,5

==> FileZ <==
1,2,3,Z,5

Некоторые моменты, на которые следует обратить внимание:

  1. некоторым awk необходимо заключать в скобки выражение с правой стороны перенаправления вывода, и
  2. некоторые awk терпят неудачу, если вы не закрываете выходные файлы по мере их поступления, и таким образом пытаются сохранить слишком много открытых файлов, когда их число превышает дюжину или около того, и
  3. сохранение нескольких открытых выходных файлов очень неэффективно во всех awk, которые это позволяют, и
  4. Построчное закрытие выходных файлов для учета этого фактора будет крайне неэффективным во всех awks.

решение2

Вы должны иметь возможность просто использовать поле в имени выходного файла. Простое решение:

awk -F, '{print > ("file_" $4 ".csv")}' Test.csv

Это работает, по крайней мере, в GNU awk и создает file_A.csvи file_B.csvт. д. Обратите внимание, что при этом все выходные файлы остаются открытыми, и чем больше их, тем медленнее процесс, особенно если вы достигнете лимита открытых файлов на процесс.

-F,устанавливает разделитель полей на запятую.

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

решение3

Что-то вроде этого:

$ awk -F, '{ print $0 >> "file-" $4 ".txt"; }' ./tmp.txt

Как упоминает ответ @ilkkachu, флаг -F— это изменение разделителя полей с пробелов по умолчанию на запятую. Вы должны использовать >>вместо  > , чтобы не перезаписывать файл, если он существует.

решение4

Питон

#!/usr/bin/python
uni=[]
k=open('file.txt','r')
for i in k:
    
    g=i.split(",")[3].strip()
    if g not in uni:
        uni.append(g)



for m in uni:
    f=open("{0}.txt".format(m),'w')
    l=open('file.txt','r')
    for d in l:
        if m in d.split(",")[3].strip():
            f.write(d)

Лучшее решение уже предоставлено в awk, это просто моя попытка

for i in `awk -F "," '{if(!seen[$4]++)print $4}' file.txt`; do awk -v i="$i" -F "," '$4==i{print $0}' file.txt >$i.txt; done

Связанный контент