2014-09-29 4 views
3

나는 ..속도까지 내 배치 파일을 구문 분석

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 파일에서 입력을 받아 배치 파일을 가지고 서버 이름, 프린터와 같은 목록에서 어떤 일을 얻기 위해 그것을 구문 분석 이름, 드라이버 이름 등을 입력하고 각 블록 항목을 쉼표로 구분 된 행에 넣습니다. 그래서 여러 줄을 가질 수 있습니다. 각각의 줄은 특정 열에 대한 정보를 가지고 있습니다. 이 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 

모든 것이 완벽하고, 코드가 의도 한대로 작동합니다 ..하지만 바로 슈퍼 괴물 천천히!

어떻게해야합니까? 문제는 true delim이없고 토큰이 다양하다는 것입니다. 예를 들어 주석에는 토큰 2가 필요하지만 프린터 이름에는 토큰 3이 필요합니다.

구문 분석의 속도를 높이려면 모든 도움이 필요합니다. 파싱하는 동안 느려진다.

+0

FWIW 코드가 확장 감지 오류 상태 "데이터를 놓친 것 같습니다. – foxidrive

답변

3

을 사용하면 매우 느립니다. 필요한 출력을 제공하는지 확인하십시오

@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 
+0

그래서 저는 약 1 분 이내에 11 개의 프린터 텍스트 파일을 모두 파싱합니다. 이 IMMENSE 개선입니다 !! 너무 감사합니다 – Alkemdah

+0

@Alkemdah : 실례합니다. 아래의 [내 솔루션] (http://stackoverflow.com/questions/26107314/speed-up-my-batch-file-parsing/26112519#26112519)이 이보다 더 빠르게 실행되어야하지만 잘못된. 이 비교가 우리 솔루션에서 사용하는 방법을 개선하는 데 도움이되기 때문에 두 프로그램의 타이밍을 게시 할 수 있다면 매우 유용 할 것입니다. TIA – Aacini

+0

@Aacini 귀하의 솔루션은 Antonio가 매우 똑똑합니다. 파일 형식이 고정되어 있으면 속도가 빠릅니다 (OP 코드 "Extended detected error state"에 나열된 마지막 데이터 지점이 누락됩니다). '1 백만 줄'의 파일에서 여러분의 코드는'59 초'를 걸리고 내 버전은'93 초' – foxidrive

6

속도는 당신이 필요로하는 경우, 내가 Marpa, 일반 BNF 파서, in Perl 좋을 것 - code, output을.

익숙해지는 데는 다소 시간이 걸리지 만 작업을 수행하고 쉽게 사용할 수있는 매우 강력한 도구를 제공합니다. 문법이 얼마나 자연스럽게 입력과 유사한 지 확인하십시오.

희망이 도움이됩니다.

3

입력 파일의 형식이 고정되어 있다고 가정합니다. 즉, 두 개의 헤더 행과 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