Повторне накладання великого файлу CSV


11

Я переглянув відповіді в цій корисній темі , але моя проблема здається досить різною, що я не можу придумати гарну відповідь (принаймні, з sed).

У мене великий файл CSV (200+ ГБ) із рядками, які виглядають так:

<alphanumerical_identifier>,<number>

де <alphanumerical_identifier>є унікальним по всьому файлу. Я хотів би створити окремий файл, який замінює перший стовпець індексом , тобто

<index>,<number>

щоб ми отримали:

1, <number>
2, <number>
3, <number>

Чи можна awkгенерувати зростаючий індекс, не завантажуючи повний файл у пам'ять?

Оскільки індекс зростає монотонно, можливо, ще краще просто знизити індекс. Чи може рішення для цього бути таким іншим?, Тобто:

<number>
<number>
<number>

Я не впевнений у доцільності цього рішення. А як же просто генерувати стільки чисел, скільки у файлі CSV, в окремому файлі, а потім просто додавати до цього файлу другий стовпець файлу CSV?
Рамеш

@Ramesh Це абсолютно добре, якщо результат правильний.
Амеліо Васкес-Рейна

2
Я підозрюю, що я щось нерозумію; інакше awk -F, '{print ++n, $2}'працювало б. Або awk -F, '{print $2}'для другої варіації.
G-Man каже: "Відновіть Моніку"

2
@ G-Man, це, мабуть, все, що хоч FNRби слугувало так само добре++n
iruvar

1
Я тричі перевірте, чи дійсно ви можете позбутися цього ідентифікатора Uniq ... чому б не додати перший (3-й) стовпець з індексом, але все ж зберегти ідентифікатор? НЕ то, що ідентифікатор , який використовується в будь-якому місці ще?
Олів’є Дулак

Відповіді:


13

Не поруч із терміналом для тестування, але як щодо часто переглянутої nlкоманди? Щось на зразок:

cut -f 2 -d , original.csv | nl -w 1 -p -s , > numbered.csv


1
PS: CSV-файл розміром 200 Гб ? Нічого собі, і я подумав, що робота з базою даних перенесених номерів у Північній Америці як CSV (пара DVD) була величезною!
єпископ

1
Це працює, хоча за номером є велике порожнє. Я замінив би це:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel

@Angel: Дякую, оновив свою відповідь, щоб використовувати параметр ширини -w 1замість лівої нумерації.
єпископ

Дякуємо @bishop - Куди ідуть вхідні та вихідні назви файлів?
Амеліо Васкес-Рейна

1
@ user815423426 Так, cutкоманда перед символом pipe ( |) дасть вам лише другий стовпець, фактично маючи неявні рядки.
єпископ

7

Ось кілька підходів, але жоден не наблизиться до швидкості cutта nlрішення вище:

  1. awk

    awk -F, '{$1=NR;print $1","$2;}' file.csv > newfile.csv
  2. Perl

    perl -pe 's/[^,]+/$./' file.csv > newfile.csv

    або

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (але я не рекомендую його для файлу 200G, це займе віки)

    i=1; while IFS=, read foo num; do 
            printf "%d,%s\n" $((i++)) $num; 
    done < file.csv > newfile.csv

Вищевказані розчини сортуються в порядку швидкості. Я протестував на своєму ноутбуці та 40-метроваму файлі, і вони взяли (в середньому 10 пробіжок) 2,22282 (awk), 2,4555 (1-й перл), 3,1825 (2-й перл) і колосальних 48,6035 за оболонку. Дуже розумне cutі nlрішення, яке ви вже мали, було приблизно в 4 рази швидше за 0.6078.


Приємно, дякую за статистику! Результат оболонки мене дещо дивує. Якщо замінити printfз echo, робить терміни значно поліпшити?
єпископ

2
40G-файл обробляється за 22222 секунди? Де я можу взяти мені цей ноутбук?
Джон Б

2
@JohnB гмм, так, вибачте, це було 40М, а не Г :)
terdon

Мені подобається скидання $1підходу до awk. cutРішення, безумовно , набагато швидше, але це і слід було очікувати , оскільки вона не замінить <alphanumerical_identifier>ні з чим. Я думаю , що найшвидший awkваріант може бути що - щось на кшталт: mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
Джон Б

@JohnB ах, так, я б припустив, що використання OFSзамість явного друку ,буде трохи швидше, і це може призвести до значної різниці у величезному файлі.
terdon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.