我有一个批处理文件,使用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是传递给批处理脚本的文件名。
这应该返回我们看到的一些常见尺寸的最高分辨率。我向社群提出的问题是:除了多次搜索文件之外,还有更快或更有效的方法吗?
答案 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
)
如果您只想匹配专用的/Height
值1650
,3300
,6600
,则可以使用此功能:
@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
循环返回最后一个数值元素,其值是最大分辨率。
答案 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
[...]
感谢大家的帮助!