批量查找唯一的单词并将100行复制到文本文件

时间:2019-05-16 09:58:14

标签: windows batch-file cmd

我有一个大文本文件,数百万行。

我很想搜索一个[unique word],并在[unique word]之前复制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

举一个我想要的例子

要放置在new_file.txt中的唯一单词之前的2行和唯一单词之后的3行

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 个答案:

答案 0 :(得分:1)

使用JREPL.BAT - a regular expression command line text processing utility

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 /批处理),可以从XP开始在任何Windows计算机上本机运行,而无需第三方exe。

JREPL比任何“纯”本地批处理解决方案都快得多。但是,它的速度不及grep这样的编译可执行文件。

答案 1 :(得分:1)

使用Select-String cmdlet及其-Context参数的PowerShell单一衬里,
分批包装:

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

答案 2 :(得分:0)

这样的变化呢? 回声%% A |找到“ yourWord” >> outputFile.txt

除非您想要使用Cygwin或PowerShell进行更复杂的搜索? 但是使用批处理脚本迭代文件行可能会非常慢,也许由CSC编译的短C#代码会更好。 让我知道你是否想要。

我的测试批次现在看起来像这样,但是除非您在处理计数在源行而不是在结果上起作用之前进行过滤(有些可能为空)。

@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();
            }
        }
    }
}

并编译在eltomjan\ETEhomeTools\CSharp\Compile.bat上在我的GitHub上发布的此类批处理文件,该搜索的灵感可能在以下某个地方找到

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 %*

如果您不想在Windows文件夹中搜索某些CSC版本。

答案 3 :(得分:0)

查找唯一单词的行号,进行一些算术运算以计算起始行和结束行。然后输出之间的线。以下代码甚至保留空行:

@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秒