awk Разделение огромного файла создает ошибку слишком много открытых файлов

У меня есть сценарий bash для разделения огромного входного файла — на данный момент он составляет 400 МБ, позже сценарий должен разделить файл размером 4 ГБ.

Ядром этой обработки является следующий awk-скрипт:

INPUTFILE="FA.txt"

awk -F $'\t' 'BEGIN{
    count = 1;
    vcount = 1;
    hcount = 1;
    tmp = 0;
    while (getline "'"$INPUTFILE"'")
    {
        FAv[count] = $1;
        FAh[count] = FAv[count];
        BK[count] = $2;
        vBreak[count] = $3;
        Count++;
    }
    close("'"$INPUTFILE"'");
}

{
    str1 = sprintf("%s%s%s",FAv[vcount],"v",".txt");
    str2 = sprintf("%s%s%s",FAh[hcount],"h",".txt");
    if (NR > (vBreak[vcount+1]-1))
    {
        close(str1);
        vcount ++;
    }
    if (($22-tmp) > BK[hcount])
    {
        close(str2);
        tmp = BK[hcount];
        hcount++;
    }
    printf "...\n",(many columns) >> str1;
    printf "...\n",(many columns) >> str2;
}' Data.txt

Data.txt — это очень большая таблица, разделенная табуляцией, содержащая около 40 столбцов и примерно 2,6 миллиона строк; файл, который сценарий должен будет обрабатывать позже, будет содержать около 30 миллионов строк. Входной файл, который я сейчас использую, должен содержать около 300 файлов, а тот, который сценарий должен обработать позже, должен создать около 4000 файлов.

Строки close(str1); и close(str2); не меняют сообщение об ошибке, которое я получаю.

awk: (filename)h.txt makes too many open files
Input record number 157762, file Data.txt
source line number 7
awk: (filename)h.txt make too many open files
Input record number 157762, file Data.txt
source line number 10

Приведенные номера строк исходного кода эквивалентны им в данном фрагменте здесь, в моем скрипте они находятся на разных позициях.

Файл «FA.txt», который используется для создания условий разделения, имеет размер 3 КБ и содержит 155 строк и 3 столбца, поэтому это не должно создавать никаких проблем для awk. Боюсь, я не могу выдавать фиктивные данные, поскольку данные исходят от компании, в которой я работаю.

Я не вижу, где проблема в коде, любая помощь будет принята с благодарностью.


person Friedrich    schedule 28.09.2015    source источник
comment
Сколько файлов у вас открыто, когда он ломается? Сколько вам нужно держать открытыми одновременно, чтобы добиться успеха? Сколько открытых файлов поддерживает ваша версия Awk и какой это Awk? Можете ли вы перейти на другую версию, если это поможет решить проблему?   -  person tripleee    schedule 28.09.2015
comment
Закрытие после каждой записи должно в любом случае обойти проблему. Очевидные поиски в Google: stackoverflow.com/questions/19643934/; stackoverflow.com/questions/23508959 /   -  person tripleee    schedule 28.09.2015
comment
Он ломается после файла 17 в этом сценарии, я использую версию awk, которая поставляется с предустановленной MAC OS X El Capitan, я не могу переключить версию awk, насколько мне известно. Я не знаю, сколько открытых файлов поддерживает моя версия awk, на самом деле мне нужно открывать только два файла одновременно. Если я правильно понял первый пост, я могу закрыть файл построчно?   -  person Friedrich    schedule 28.09.2015
comment
похоже проблема в логике, т.е. в цикле if (NR > (vBreak[vcount+1]-1)) оператор close(str1) закрывает файл, но так как имя файла не меняется до следующей итерации, последний printf перенаправляется на все еще исходный str1 снова открывает файл   -  person ewcz    schedule 28.09.2015
comment
просто поместите операторы close сразу после printf   -  person ewcz    schedule 28.09.2015
comment
Я поместил команды печати, а затем получил операторы if, которые решили проблему с сообщением об ошибке, теперь я переместил команды печати и закрытия вниз, я посмотрю, что работает лучше для меня. Большое спасибо!   -  person Friedrich    schedule 28.09.2015
comment
@tripleee: мне все еще нужен ответ на этот вопрос: можно ли закрывать файлы построчно, используя awk?   -  person Friedrich    schedule 28.09.2015
comment
Помимо реальной проблемы, на которую указал EWCZ, Count++;, вероятно, должно быть count++;. Ваши массивы FAv и FAh равны, вы, вероятно, можете немного упростить, используя только один. Если вы хотите использовать GNU awk, вы можете установить macport, а затем GNU awk.   -  person Renaud Pacalet    schedule 28.09.2015
comment
Count++ - это подарок от Internet Explorer, которым я пользуюсь прямо сейчас, потому что он думает, что должен все время исправлять меня, в моем коде это count++. Массивы одинаковы, у меня были они оба из-за разных счетчиков и удобочитаемости, возможно, я собираюсь изменить это позже, когда скрипт заработает правильно. У меня уже установлен brew, но на моем рабочем месте нет интернета, поэтому я не смогу его попробовать, кроме того, я доволен Mac awk на данный момент - вы знаете какие-то его недостатки?   -  person Friedrich    schedule 28.09.2015