3

У меня около 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 файлов должно быть 160000 файлов, но только с 8000 итераций команды поиска.

РЕДАКТИРОВАТЬ 2: вот решение с помощью команд Linux. Я, вероятно, в конечном итоге просто использовать это, если у кого-то нет лучшего способа

grep -f 12/20/2015 12/22/2015 filein1 > intermediate
awk -F, '{print > $1".out"}' intermediate

Это двухэтапный процесс, который сначала фильтрует даты, а затем разбивает результат по дате.

3 ответа3

4

Я не хочу проходить через каждый из входных файлов более одного раза.

Перебирать каждую из дат не получится. Я хочу разделить каждый из выходных файлов в один файл на дату.

О, почему ты просто не сказал никаких повторений из цикла! ! , , ,

Решение 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= value будет полным путем к месту, где находится.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
2

Однострочное использование PowerShell:

get-content c:\filein.txt | where-object { $_ -match "12/22/2015" } | out-file c:\fileout22.txt

2
findstr -rc:"12/2[02]/2015" filein > fileout

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .