Parsing 加快批处理文件解析速度

Parsing 加快批处理文件解析速度,parsing,batch-file,Parsing,Batch File,我有一个批处理文件,它从一个类似如下的txt文件中获取输入 Microsoft (R) Windows Script Host Version 5.8 Copyright (C) Microsoft Corporation. All rights reserved. Server name lak-print01 Printer name Microsoft XPS Document Writer Share name Driver name Microsoft XPS Document

我有一个批处理文件,它从一个类似如下的txt文件中获取输入

Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.


Server name lak-print01
Printer name Microsoft XPS Document Writer
Share name 
Driver name Microsoft XPS Document Writer
Port name XPSPort:
Comment 
Location 
Print processor WinPrint
Data type RAW
Parameters 
Attributes 64
Priority 1
Default priority 1
Average pages per minute 0
Printer status Idle 
Extended printer status Unknown 
Detected error state Unknown 
Extended detected error state Unknown 

Server name lak-print01
Printer name 4250_Q1
Share name 4250_Q1
Driver name Canon iR5055/iR5065 PCL5e
Port name IP_192.168.202.84
Comment Audit Department in Lakewood Operations
Location Operations Center
Print processor WinPrint
Data type RAW
Parameters 
Attributes 10826
Priority 1
Default priority 0
Average pages per minute 0
Printer status Idle 
Extended printer status Unknown 
Detected error state Unknown 
Extended detected error state Unknown 

Server name lak-print01
Printer name 3130_Q1
Share name 3130_Q1
Driver name Canon iR1020/1024/1025 PCL5e
Port name IP_192.168.202.11
Comment Canon iR1025 
Location Operations Center
Print processor WinPrint
Data type RAW
Parameters 
Attributes 10824
Priority 1
Default priority 0
Average pages per minute 0
Printer status Idle 
Extended printer status Unknown 
Detected error state Unknown 
Extended detected error state Unknown 
并对其进行解析以获取列表中的某些内容,如服务器名称、打印机名称、驱动程序名称等。。然后将每个块条目放入其自己的逗号删除行中。所以我可以有多行,每一行对应一块文本,每一列都有特定的信息。其中一些txt文件有100多个条目。在解析时,我尝试解析的每个文件都需要5-10分钟

解析代码如下所示

:Parselak-print01
SETLOCAL enabledelayedexpansion
:: remove variables starting $
FOR  /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
(FOR /f "delims=" %%a IN (lak-print01.txt) DO CALL :analyse "%%a")>lak-print01.csv
attrib +h lak-print01.csv
GOTO :EOF

:analyse
SET "line=%~1"
SET /a fieldnum=0
FOR %%s IN ("Server name" "Printer name" "Driver name"
            "Port name" "Location" "Comment" "Printer status" 
        "Extended detected error state") DO CALL :setfield %%~s
GOTO :eof

:setfield
SET /a fieldnum+=1
SET "linem=!line:*%* =!"
SET "linet=%* %linem%"
IF "%linet%" neq "%line%" GOTO :EOF 
IF "%linem%"=="%line%" GOTO :EOF
SET "$%fieldnum%=%linem%"
IF NOT DEFINED $8 GOTO :EOF 
SET "line="
FOR /l %%q IN (1,1,7) DO SET "line=!line!,!$%%q!"
ECHO !line:~1!
:: remove variables starting $
FOR  /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
GOTO :eof
我得到的结果是

lak-print01,Microsoft XPS Document Writer,Microsoft XPS Document Writer,XPSPort:,,,Idle 
lak-print01,4250_Q1,Canon iR5055/iR5065 PCL5e,IP_192.168.202.84,Operations Center,Audit Department in Lakewood Operations,Idle 
lak-print01,3130_Q1,Canon iR1020/1024/1025 PCL5e,IP_192.168.202.11,Operations Center,Canon iR1025 ,Idle 
lak-print01,1106_TRN,HP LaserJet P2050 Series PCL6,IP_172.16.10.97,Monroe,HP P2055DN,Idle 
lak-print01,1101_TRN,HP LaserJet P2050 Series PCL6,IP_10.3.3.22,Burlington,Training Room printer,Idle 
lak-print01,1096_Q3,Canon iR1020/1024/1025 PCL5e,IP_192.168.96.248,Silverdale,Canon iR 1025,Idle 
lak-print01,1096_Q2,Kyocera Mita KM-5035 KX,IP_192.168.96.13,Silverdale,Kyocera CS-5035 all in one,Idle 
lak-print01,1096_Q1,HP LaserJet P4010_P4510 Series PCL 6,IP_192.168.96.12,Silverdale,HP 4015,Idle 
lak-print01,1095_Q3,HP LaserJet P4010_P4510 Series PCL 6,IP_192.168.95.247,Sequim,HP LaserJet 4015x,Idle 
一切都很完美,代码按预期工作。。但是它的速度太慢了

我如何加快速度?问题是没有真正的delim,代币也不尽相同。。例如,注释需要标记2,但打印机名称需要标记3


是否有助于提高解析速度。。程序运行得很好,但在解析过程中速度非常慢。

使用
Call
非常慢-看看这是否能提供您所需的输出,比较一下它的速度会有多快

@echo off
:Parselak-print01
SETLOCAL enabledelayedexpansion
(FOR /f "delims=" %%a IN (lak-print01.txt) DO (
for /f "tokens=1,2,*" %%b in ("%%a") do (
   if "%%b"=="Server"   set "server=%%d"
   if "%%b"=="Printer"  if "%%c"=="name" (set "printer=%%d") else (set "printerstatus=%%d")
   if "%%b"=="Driver"   set "driver=%%d"
   if "%%b"=="Port"     set "port=%%d"
   if "%%b"=="Location" for /f "tokens=1,*"   %%e in ("%%a") do set "location=%%f"
   if "%%b"=="Comment"  for /f "tokens=1,*"   %%e in ("%%a") do set "comment=%%f"
   if "%%b"=="Extended" for /f "tokens=1-4,*" %%e in ("%%a") do if "%%f"=="detected" set "extendeddetected=%%i"
   )
if defined extendeddetected (
   echo !server!,!printer!,!driver!,!port!,!location!,!comment!,!printerstatus!,!extendeddetected!
   set "server="
   set "printer="
   set "driver="
   set "port="
   set "location="
   set "comment="
   set "printerstatus="
   set "extendeddetected="
)
))>lak-print01.csv
attrib +h lak-print01.csv
pause

如果速度是你所需要的,我建议,一个通用的BNF解析器,-

这将需要一些时间来适应,但这项工作,并为您提供了一个非常强大的工具,您可以轻松使用-请注意,语法与输入非常相似


希望这有帮助。

下面的解决方案假设输入文件具有固定格式,即它有两个标题行,后面是18行的块,始终按相同的顺序排列。如果这是真的,这个解决方案以非常快的方式生成输出;否则,必须对其进行相应修改

@echo off
setlocal EnableDelayedExpansion

rem Create the array of variable names for the *desired rows* of data in the file
set "row[1]=Server name"
set "row[2]=Printer name"
set "row[4]=Driver name"
set "row[5]=Port name"
set "row[6]=Comment"
set "row[7]=Location"
set "row[15]=Printer status"

set i=0
(for /F "skip=2 delims=" %%a in (lak-print01.txt) do (
   set /A i+=1
   if defined row[!i!] (
      set "line=%%a"
      for %%i in (!i!) do for /F "delims=" %%v in ("!row[%%i]!") do set "%%v=!line:*%%v =!"
   )
   if !i! equ 18 (
      echo !Server name!,!Printer name!,!Driver name!,!Port name!,!Location!,!Comment!,!Printer status!
      set i=0
   )
)) > lak-print01.csv

FWIW您的代码似乎错过了
“扩展检测到的错误状态”
数据。因此。。我在大约1分钟或更短的时间内解析了所有11个打印机文本文件。这是一个巨大的进步!!谢谢你,苏MUCH@Alkemdah:对不起。我很确定下面的应该比这个跑得快,但我可能错了。如果您可以发布这两个程序的时间安排,这将非常有用,因为这种比较将帮助我们改进解决方案中使用的方法。TIA@Aacini您的解决方案非常聪明,如果文件格式是固定的,那么它会更快(但它错过了最后一个数据点,该数据点仅列在操作代码“扩展检测到的错误状态”中)。在一个
100万行的文件上
你的代码需要
59秒
而我的版本需要
93秒
@foxidrive:谢谢你的计时结果!为了在输出中添加最后一个数据字段,只需在所需行中添加
set“row[18]=Extended detected error state”
,并且在
echo
命令中添加相同的变量…@mvp:这种“完整工作解决方案”产生的变量不是OP所要求的,我看不到输入文件名在Perl代码中的位置(在本例中为“lak-print01.txt”)。。。