Пакет, чтобы найти уникальное слово и скопировать 100 строк в текстовый файл - PullRequest
0 голосов
/ 16 мая 2019

У меня большой текстовый файл. Миллионы строк.

Я бы хотел найти [уникальное слово] и скопировать 30 строк до и 100 строк после [уникального слова] и вывести строки в другоефайл.

желательно именовать как [уникальное слово] .txt

Я нашел это, но в нем нет поиска.

DOS Batch To Copy First 100 Lines Of A Text File<<<

@ECHO OFF
setlocal enabledelayedexpansion

SET /P maxlines=Enter number of lines to be moved to new txt document: 
SET /A linecount=0

FOR /F "delims=" %%A IN (textfile1.txt) DO ( 
  IF !linecount! GEQ %maxlines% GOTO ExitLoop
 ECHO %%A >> C:\users\username\desktop\textfile2.txt
 SET /A linecount+=1
)

:ExitLoop
ECHO All Done.
ECHO.
ECHO Press any key to close this window.
PAUSE>NUL
EXIT

, чтобы привести пример, который я хочу

2 строки перед уникальным словом и 3 строки после уникального слова, которые будут помещены в new_file.txt

sorce_file.TXT имеет это содержимое

world 1
world 2
world 3
world 4
world 5
unique word
world 6
world 7
world 8
world 9
world 10

Я запускаю сценарий, а вывод new_file.txt имеет это

world 4
world 5
unique word
world 6
world 7
world 8

Ответы [ 4 ]

1 голос
/ 16 мая 2019

Один вкладыш PowerShell, использующий командлет Select-String с параметром -Context,
в упаковке:

powershell -NoP -C "Select-String -Path .\Source_File.txt -Pattern 'unique word' -Context 30,100|ForEach-Object{$_.Context.PreContext;$_.Line;$_.Context.PostContext}|Set-Content New_File.txt"

Должно быть быстрее, чем чистая партия.

Пример вывода с -Context 2,3

> Get-Content .\New_File.txt
world 4
world 5
unique word
world 6
world 7
world 8
1 голос
/ 16 мая 2019

Использование JREPL.BAT - утилита обработки текста в командной строке регулярного выражения :

jrepl "UniqueWord" "" /L /K 30:100 /F "input.txt" /O "UniqueWord.txt"

Или игнорировать слова, в которых UniqueWord встроен в большее слово:

jrepl "\bUniqueWord\b" "" /K 30:100 /F "input.txt" /O "UniqueWord.txt"

Используйте jrepl /?help, чтобы получить список всей доступной документации в сценарии.

JREPL - это чистый сценарий (гибридный JScript / пакетный), который работает на любом компьютере под управлением Windows начиная с XP и далее без необходимости.для стороннего exe.

JREPL намного быстрее, чем любое «чистое» решение для пакетной обработки.Не так быстро, как скомпилированный исполняемый файл, такой как grep.

1 голос
/ 16 мая 2019

Как насчет таких изменений? ЭХО %% A | найти "твое слово" >> outputFile.txt

Если вам не нужен более сложный поиск с использованием Cygwin или PowerShell? Но это может быть довольно медленным, чтобы перебрать строки файла, используя пакетный скрипт, может быть, короткий код C #, скомпилированный CSC, будет работать лучше ... Дайте мне знать, если хотите.

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

@ECHO OFF
setlocal enabledelayedexpansion
del textfile2.txt

SET /A maxlines=10
SET /P maxlines=Enter number of lines to be moved to new txt document: 

SET /A linecount=0

FOR /F "delims=" %%A IN (x.txt) DO (
 IF !linecount! GEQ %maxlines% GOTO ExitLoop
 SET /A linecount+=1
 ECHO %%A | find ";" >> textfile2.txt
)

:ExitLoop
ECHO All Done.

В случае, если версия C # может выглядеть, например, (предположим, немного более читабельно по сравнению с пакетными сценариями):

using System;
using System.Collections.Generic;
using System.IO;

namespace BatchTest
{
    class Program
    {
        public static void Main(string[] args)
        {
            String inFile = args[0], outFile = args[1], word = args[2], line;
            int nextLines = 100;

            Queue<String> qt = new Queue<String>();
            using (StreamReader sr = new StreamReader(inFile))
            using (StreamWriter sw = new StreamWriter(outFile))
            while ((line = sr.ReadLine()) != null)
            {
                qt.Enqueue(line);
                if (line.Contains(word))
                {
                    foreach (var el in qt)
                    {
                        sw.WriteLine(el);
                    }
                    qt.Clear();
                    int i = nextLines;
                    while ((i-- > 0) && (line = sr.ReadLine()) != null)
                    {
                        if (line.Contains(word)) i = nextLines;
                        sw.WriteLine(line);
                    }
                } else if (qt.Count > 29) qt.Dequeue();
            }
        }
    }
}

И скомпилируйте пакетный файл, подобный этому, опубликованный на моем GitHub в eltomjan \ ETEhomeTools \ CSharp \ Compile.bat
Вдохновение для этого поиска, найденное где-то здесь, вероятно:

setlocal enabledelayedexpansion enableextensions
set LIBS=
for %%x in (*.dll) do (
  echo %%x|findstr ",">nul 2>&1
  if errorlevel 1 (set LIBS=!LIBS!,%%x) else (set LIBS=!LIBS!,"%%x")
)
if "%LIBS%"=="" (for /F %%v in ('dir /s %WINDIR%\Microsoft.NET\csc.exe /B') do echo %%v -debug %%* > cscLatest.bat ) else (for /F %%v in ('dir /s %WINDIR%\Microsoft.NET\csc.exe /B') do echo %%v -debug /r:%LIBS:~1% %%* > cscLatest.bat )
if "%1" == "" cscLatest.bat *.cs
cscLatest.bat %*

Если вы не хотите искать какую-либо версию CSC в папках Windows.

0 голосов
/ 16 мая 2019

найдите номер строки вашего уникального слова, сделайте некоторую арифметику, чтобы вычислить начальную и конечную строки. Затем выведите строки между. Следующий код даже сохраняет пустые строки:

@echo off
setlocal 
set "file=yourfile.txt"

for /f "tokens=1 delims=[]" %%a in ('find /n "[unique word]" "%file%"') do set line=%%a
set /a startline=line-30
set /a endline=line+100
if %startline% lss 1 (set "skip=") else (set "skip=skip=%startline%")

set /a count=startline
for /f "%skip% tokens=1,* delims=:" %%a in ('findstr /n "^" "%file%"') do (
  if !count! geq %endline% goto :done
  echo(%%b 
  set /a count+=1
)
:done

Только не ожидайте, что это будет быстро ... В моей системе для файла с 11500 строками требуется около 10 секунд

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...