Windows Batch Scripting:检查多个字符串的文件

时间:2018-04-05 19:18:12

标签: batch-file

我有一个批处理文件,使用ghostscript处理扫描的PDF。用户提示之一是用于解析所需输出。我写了一个粗略的自动检测例程:

for /f "delims=" %%a in ('findstr /C:"/Height 1650" %1') do set resdect=150
for /f "delims=" %%a in ('findstr /C:"/Height 3300" %1') do set resdect=300
for /f "delims=" %%a in ('findstr /C:"/Height 6600" %1') do set resdect=600
echo %resdect% DPI detected.

%1是传递给批处理脚本的文件名。

这应该返回我们看到的一些常见尺寸的最高分辨率。我向社群提出的问题是:除了多次搜索文件之外,还有更快或更有效的方法吗?

4 个答案:

答案 0 :(得分:4)

假设RESDECT的值是/Height除以11,并且没有行包含多个/Height令牌,则以下代码可能适用于你:

@echo off
for /F delims^=^ eol^= %%A in ('findstr /R /I /C:"/Height  *[0-9][0-9]*" "%~1"') do (
    set "LINE=%%A"
    setlocal EnableDelayedExpansion
    set "RESDECT=!LINE:*/Height =!"
    set /A "RESDECT/=11"
    echo/!RESDECT!
    endlocal
)

如果您只想匹配专用的/Height165033006600,则可以使用此功能:

@echo off
for /F delims^=^ eol^= %%A in ('findstr /I /C:"/Height 1650" /C:"/Height 3300" /C:"/Height 6600" "%~1"') do (
    set "LINE=%%A"
    setlocal EnableDelayedExpansion
    set "RESDECT=!LINE:*/Height =!"
    set /A "RESDECT/=11"
    echo/!RESDECT!
    endlocal
)

要收集文件中出现的最高 /Height值,您可以使用此脚本,尊重上述假设:

@echo off
set "RESDECT=0"
for /F delims^=^ eol^= %%A in ('findstr /R /I /C:"/Height  *[0-9][0-9]*" "%~1"') do (
    set "LINE=%%A"
    setlocal EnableDelayedExpansion
    set "HEIGHT=!LINE:*/Height =!"
    for /F %%B in ('set /A HEIGHT/11') do (
        if %%B gtr !RESDECT! (endlocal & set "RESDECT=%%B") else endlocal
    )
)
echo %RESDECT%

当然,您可以再次像上面那样交换findstr命令行。

这是获取最大/Height值的另一种方法,使用(伪)数组,这可能比上述方法更快,因为在循环中没有创建额外的cmd实例:

@echo off
setlocal
set "RESDECT=0"
for /F delims^=^ eol^= %%A in ('findstr /R /I /C:"/Height  *[0-9][0-9]*" "%~1"') do (
    set "LINE=%%A"
    setlocal EnableDelayedExpansion
    set "HEIGHT=!LINE:*/Height =!"
    set /A "HEIGHT+=0, RES=HEIGHT/11" & set "HEIGHT=0000000000!HEIGHT!"
    for /F %%B in ("$RESOLUTIONS[!HEIGHT:~-10!]=!RES!") do endlocal & set "%%B"
)
for /F "tokens=2 delims==" %%B in ('set $RESOLUTIONS[') do set "RESDECT=%%B"
echo %RESDECT%
endlocal

首先,所有高度和相关分辨率都收集在名为$RESOLUTIONS[]的数组中,其中/Height值用作索引,分辨率是值。高度变为左零填充到固定的数字位数,因此set $RESOLUTIONS[按升序返回它们。第二个for /F循环返回最后一个数值元素,其值是最大分辨率。

我必须承认,这是受Aacini的好answer的启发。

答案 1 :(得分:2)

获取变量的相应行并使用它而不是整个文件。当你稍微改变一下逻辑时,你可以只用一个for循环而不是你的三个@echo off setlocal enabledelayedexpansion for /f "delims=" %%a in ('findstr /C:"/Height " %1') do ( set "line=%%a" set "line=!line:*/Height =!" for /f "delims=/ " %%b in ("!line!") do set "hval=!hval! %%b" ) for %%a in (1650,3300,6600) do @( echo " %hval% " | find " %%a " >nul && set /a resdect=%%a/11 ) echo %resdect% DPI detected. 循环:

for /f %a in ('type t.txt^|find "/Height "^|jrepl ".*/Height ([0-9]{4}).*" "$1"^|sort') do set /a dpi==%a / 11

jrepl.bat的解决方案可能类似于:

%%a

(给定,所有有效高度都有4位数)
注意:要在批量文件中使用,请使用%a代替jrepl
我几乎没有抓到$matches = Select-String '(?<=<B>).+?(?=</B>)' $matches | ForEach-Object { $_.Matches.Value } 的表面 - 我很确定,有一个更优雅(可能更快)的解决方案。

答案 2 :(得分:2)

您可以使用array在单个操作中将高度值直接转换为最高分辨率。但是,要做到这一点,我们需要知道包含高度值的行的格式。在下面的代码中,我假设这样一行的格式是/Height xxxx,也就是说,高度是行中的第二个标记。如果不是这样,只需调整"tokens=2"命令中的for /F值。

编辑根据评论中的要求修改了代码

在此修改后的代码中,高度值可能出现在该行的任何位置。

@echo off
setlocal EnableDelayedExpansion

rem Initialize "resDect" array
for %%a in ("1650=150" "3300=300" "6600=600") do (
   for /F "tokens=1,2 delims==" %%b in (%%a) do (
      set "resDect[%%b]=%%c"
   )
)

set "highResDect=0"
for /F "delims=" %%a in ('findstr "/Height" %1') do (
   set "line=%%a"
   set "line=!line:*/Height =!"
   for /F %%b in ("!line!") do set /A "thisRectDect=resDect[%%b]"
   if !thisRectDect! gtr !highResDect! set "highResDect=!thisRectDect!"
)

echo %highResDect% DPI detected.

答案 3 :(得分:0)

为了记录,最终的代码是:

setlocal enabledelayedexpansion
set resdetc=0
for /f "delims=" %%a in ('findstr /C:"/Height " %1') do (
  set "line=%%a"
  set "line=!line:*/Height =!"
  for /f "delims=/ " %%b in ("!line!") do set "hval=!hval! %%b" 
)
for %%a in (1650,3300,6600) do @(
  echo " %hval% " | find " %%a " >nul && set /a resdetc=%%a/11
)
if %resdetc%==0   SET resDefault=3
if %resdetc%==150 SET resDefault=1
if %resdetc%==300 SET resDefault=3
if %resdetc%==600 SET resDefault=6

ECHO.
ECHO Choose your resolution
ECHO ----------------------
ECHO 1. 150    4. 400
ECHO 2. 200    5. 500
ECHO 3. 300    6. 600
ECHO.
IF NOT %RESDETC%==0 ECHO 7. Custom    (%resdetc% DPI input detected)
IF     %RESDETC%==0 ECHO 7. Custom
ECHO ----------------------
choice /c 1234567 /T 3 /D %resDefault% /N /M "Enter 1-7 (defaults to %resDefault% after 3 sec.): "
IF errorlevel==7 goto choice7
IF errorlevel==6 set reschoice=600 & goto convert
IF errorlevel==5 set reschoice=500 & goto convert
[...]

感谢大家的帮助!