Фильтрация и разбиение огромного файла на основе столбца Windows
У меня около 2 ТБ файлов данных, отформатированных как
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/21/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
и я хочу вытащить определенные даты. Например, я мог бы хотеть генерировать файлы для 20.12.2015 и 22.12.2015.
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
12/20/2015 somerandomdata
а также
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
12/22/2015 somerandomdata
Я мог бы легко сделать это с помощью grep в Linux, выполнив grep '12/20/2015' filein > fileout20
а также grep '12/22/2015' filein > fileout22
но это имеет две проблемы.
Во-первых, что более важно, он должен дважды просмотреть входной файл, чтобы сгенерировать вывод. С 2 ТБ данных и несколькими датами на файл это серьезная проблема. (Связанный: я также не хочу решений, которые разбивают файл на каждую возможную дату, потому что я не буду хотеть данных за большинство дат, только приблизительно 10% от каждого входного файла)
Вторая проблема заключается в том, что мне нужно запустить это на Windows. (Я понимаю, что большинство команд Linux имеют Windows-эквивалент, использующий GnuWin32 или тому подобное, так что это не такая большая проблема)
Есть ли способы, которыми это можно сделать эффективно?
РЕДАКТИРОВАТЬ: ответы до сих пор имеют одну из двух проблем, поэтому я поясню немного. Первая проблема заключается в том, что я не хочу проходить через каждый входной файл более одного раза. Таким образом, наличие цикла для перебора каждой из дат не будет работать. Это потому, что если у меня есть 200 дат и 8000 файлов, это заняло бы 1 600 000 итераций.
Вторая проблема заключается в том, что я хочу разбить каждый из выходных файлов на один файл за дату.
Таким образом, с 200 датами и 8000 файлов должно быть 1 600 000 файлов, но только с 8000 итерациями команды поиска.
РЕДАКТИРОВАТЬ 2: вот решение с помощью команд Linux. Я, вероятно, в конечном итоге просто использовать это, если у кого-то нет лучшего способа
grep -f 12/20/2015 12/22/2015 filein1 > intermediate
awk -F, '{print > $1".out"}' intermediate
Это двухэтапный процесс, который сначала фильтрует даты, а затем разбивает результат по дате.
3 ответа
Я не хочу проходить через каждый из входных файлов более одного раза.
Перебирать каждую из дат не получится. Я хочу разделить каждый из выходных файлов в один файл на дату.
О, почему ты просто не сказал никаких повторений из цикла! ! , , ,
Решение PowerShell
(Установите соответствующие переменные в следующем примере: список строк, путь к выходному файлу и, возможно, имя строковой переменной в формате MMDDYYYY)
Select-String -Path "C:\Path\*.txt" -Pattern 12/20/2015,12/23/2015,12/30/2015 -AllMatches | foreach-object {
$RS = $_.Matches[0].Groups[0].Value.Replace("/","")
$RS | Out-File "C:\Path\$RS.txt" -Append
}
(Выше приведено решение PowerShell для поиска всего содержимого текстового файла в определенном каталоге по списку строк. Оно также добавит все найденные строковые значения в выходной файл с допустимым именем файла, совпадающим с шаблоном сопоставленной строки, и это уникально для эта строка.)
Вот решение с помощью команд Linux. Я, вероятно, в конечном итоге просто использовать это
grep -f 12/20/2015 12/22/2015 filein1 > intermediate
awk -F, '{print > $1".out"}' intermediate
Это двухэтапный процесс, который сначала фильтрует даты, а затем разбивает результат по дате.
Итак, вы ищете содержимое текстовых файлов в определенном каталоге со списком строк. Для каждой подходящей строки, найденной в каждом файле, необходимо, чтобы ее значение было записано (и добавлено, если применимо) в файл с "допустимым" именем файла, уникальным для данной строки - без разных строк в одних и тех же файлах.
Что касается того, чтобы быть "лучшим" способом, то это действительно вопрос мнения в зависимости от того, что вы измеряете, статистику и ресурсы, я полагаю. Я не знал, что вы очень беспокоились об оптимальном быстродействующем решении по сравнению с тем, как вы работали.
(Я оставлю решение для пакетного сценария ниже на тот случай, если кто-нибудь найдет его полезным.)
Я хочу вытащить определенные даты. Например, я мог бы хотеть генерировать файлы для 20.12.2015 и 22.12.2015.
Комментарий
Однако, если я не пойму неправильно findstr, будет только один выходной файл вместо одного на дату, что не является поведением, которое я ищу.
Это расширит другое решение, чтобы дать вам строковое имя файла для добавления к исходному имени файла плюс MMDDYYYY
или же YYYYMMDD
или даже, возможно, любая комбинация или отдельные символы YYYY
, MM
, или же DD
части соответствующей строки для добавления к имени файла ТЕ строк, найденных для файла - как вы объяснили.
В основном вы просто устанавливаете свои переменные соответственно, сохраняете как пакетный скрипт [.cmd], а затем просто запускаете его. Большинство переменных будут явными для конкретного полного пути применимых каталогов.
Пакетный скрипт Переменная Объяснения
SET FilePath=
значением будет полный путь к папке, в которой находятся файлы.TXT, которые вы будете искатьSET StringList=
значением будет полный путь и имя файла, в котором вы будете сохранять текстовый файл с каждой строкой (т.е.12/20/2015
,12/22/2015
и т. д.) искать в.txt
файлы. Вы поместите строку в каждую строку в файле, которая будет использоваться в качестве строки для поиска в.txt
файлы (см. пример ниже).Я собираюсь предположить, что другие переменные и остальная логика пакетного сценария имеют смысл; в противном случае, дайте мне знать, и я буду рад добавить дополнительные маркеры для уточнения и т. д.
Пример сценария
@ECHO ON
SET FilePath=C:\Path\<Location containing .TXT files to search>
SET StringList=C:\Path\DateList.txt
FOR %%A IN ("%FilePath%\*.txt") DO FOR /F "TOKENS=*" %%B IN (%StringList%) DO CALL :FindConCat "%%~B" "%%~NFXA" "%%~NA" "%%~XA"
GOTO EOF
:FindConCat
SET SearchStr=%~1
SET SearchFile=%~2
SET OutFName=%~3
SET FileExt=%~4
SET ParseStr=%SearchStr%
:::: --// MMDDYYY format
SET ParseStr=%ParseStr:~0,2%%ParseStr:~3,2%%ParseStr:~6,4%
:::: --// YYYYMMDD format
:: SET ParseStr=%ParseStr:~6,4%%ParseStr:~0,2%%ParseStr:~3,2%
FINDSTR /c:"%SearchStr%" "%SearchFile%">>"%FilePath%\%OutFName%_%ParseStr%%FileExt%"
GOTO EOF
ПРИМЕР СТРОИТЕЛЬНОГО СПИСКА ФАЙЛ СОДЕРЖАНИЕ ( SET StringList=C:\Path\DateList.txt
)
12/15/2015
12/22/2015
12/23/2015
12/24/2015
Однострочное использование PowerShell:
get-content c:\filein.txt | where-object { $_ -match "12/22/2015" } | out-file c:\fileout22.txt