Последняя строка неверна при разбиении файла на awk

У меня есть файл main.txt с данными, который выглядит так:

 20130826,aaaaaaaaaaaaaa,bbbbbbb 20130826,sdfasdfasdfas,sdfasdfasd 20130826,dfasdfas,asdf2323 ... 20130827,sfasdfasdfasd,sdfasdfwea 

Я использовал следующий фрагмент awk для разделения main.csv на меньшие файлы по дате.

 cat test01 | stdbuf -oL -eL awk -F',' '{print $2","$3 >> "data"$1".csv"; fflush()}' 

и я обнаружил, что для разбитого файла data20130826.csv последняя строка неполна,

 ... 20130826,dfasdfas,asdf2323 2013082 

на самом деле последние несколько строк (10 или около того) даты 20130826 отсутствуют, они также не находятся в data20130827.csv. Я попытался отключить буферизацию, как в приведенной выше строке, но, похоже, это не помогает. Я уверен, что основной файл в порядке. Что случилось? Я использую GNU Awk 4.0.1.

  • Убедитесь, что stdout подключен к терминалу из сценария AWK
  • Манипулирование линиями с неупорядоченными полями
  • Как преобразовать часовой пояс в журналы, поскольку они хвостают
  • Сравните 2 файла с разделителями табуляции и выходных различий с заголовком столбца
  • Тестирование регулярного выражения из stdin с помощью grep | sed | awk
  • сортировать и uniq в awk
  • как фильтровать внутренние кавычки?
  • Дата реформата для отметки времени unix в таблице csv
  • 2 Solutions collect form web for “Последняя строка неверна при разбиении файла на awk”

    Чтобы уточнить мой первоначальный пост: я согласен с Орионом и сомневаюсь, что это ошибка awk. Я тоже не буду беспокоиться об этом. Я думаю, что это просто проблема awk, вызванная данными. В частности, я думаю, что у вас может быть слишком много открытых файловых дескрипторов – по одному для каждой даты в вашем файле. Или, возможно, вы достигли ограничения на буфер по той же причине – слишком много открытых файлов. fflush не закрывает открытые файлы – он просто очищает буферы.

    Итак, сколько разных дат во входном файле? Thats, сколько открытых файлов у вас будет:

     cut -d"," -f1 test01 | sort | uniq | wc -l 

    – если это много (сотни), то см. мое второе предложение относительно закрытия файлов по ходу дела.

    Два предложения:
    1. Вы уверены, что данные являются простым текстом без каких-либо скрытых символов, таких как обратные пространства, а также имеют нормальные окончания строки UNIX? Можете ли вы выровнять строки с префиксом «20130826», чтобы увидеть, что они выглядят нормальными и действительно являются отдельными строками, т.е.

     cat test01 | grep "^20130826" - and also run cat test01 | grep -c "^20130826" 

    – подтвердить, что количество строк grep соответствует тому, что находится в выходном файле (или нет)

    2. Если входные данные отсортированы в порядке дат, вы можете попытаться закрыть файлы по мере их написания: я тестировал это с момента моего первоначального сообщения, и он работал нормально:

     cat test01 | awk -F"," '{prevfile=ofile; ofile=sprintf("data%s.csv",$1); if (NR > 1 && ofile != prevfile) close(prevfile); print $2","$3 >> ofile}' 

    Этот код по-прежнему будет работать, если ваш файл не сортируется по дате, но будет чаще открывать и закрывать файлы. В этом случае просто измените «cat test01» на «sort test01» в начале команды.

    Вы не всегда должны закрывать файлы явно при использовании awk, но я знаю по опыту, что awk используется для сбоя, если вы написали много таких файлов, не закрывая их. Возможно, это по-прежнему применяется, поскольку я думаю, что это связано с лимитом в дескрипторах открытых файлов.

    Также, когда вы добавляете эти файлы, убедитесь, что они не содержат никаких данных перед запуском команды. Легко забыть, когда что-то не работает …

    Пытаться:

     $ cat test01 | stdbuf -oL -eL awk -F',' '{print $2","$3 >> "data"$1".csv"; fflush("")}' 

    В gawk 4.0.1 , вызывающий fflush () без каких-либо аргументов, только flush stdout. Вам нужно вызвать fflush() с пустой строкой "" чтобы awk очистил все открытые выходные файлы и трубы.

    С gawk 4.0.2 и более поздними gawk 4.0.2 , если аргументов нет, или аргумент для fflush() является пустой строкой "" , тогда awk очищает буферы для всех открытых выходных файлов и труб.

    Linux и Unix - лучшая ОС в мире.