我正在编写批处理,用户必须输入要作为批处理参数激活的设备列表。该列表可以包含随机顺序的设备号和/或名称以及可能的重复和残留物(即,不存在或不存在就绪设备)。批处理:default 部分以随机顺序存储所有当前就绪设备的数组 dev _#= name 。初始任务是过滤用户输入以排除重复项和残留项,并显示要激活的已排序的准备好的设备号列表。然后激活该列表中的设备。什么样的高效短代码可以完成过滤任务?
@echo off
setlocal EnableDelayedExpansion
:default
set "dev_1=AB" & set "dev_2=BA" & set "dev_3=AC" & set "dev_16=CA" & set "dev_19=BC" & set "dev_6=CB" & set "dev_7=ZA"
set "dev_8=AZ" & set "dev_29=UA" & set "dev_10=YZ" & set "dev_18=YW" & set "dev_12=AK" & set "dev_13=AJ" & set "dev_14=HT"
rem batch arguments entered by user
rem 1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA
rem Desired sorted filtered output
rem 1 2 3 6 7 10 12
答案 0 :(得分:6)
使用本机批处理命令的一个班轮 - 没办法!
但它并没有占用大量代码,特别是如果你在设计一些数据结构方面具有创造性。请注意,唯一重要的代码是:test
例程。其余的是初始化和测试用例。
@echo off
setlocal
:: Clear devices
for /f "delims==" %%A in ('set dev. 2^>nul') do set "%%A="
:: Define devices
for %%A in (
" 1=AB" " 2=BA" " 3=AC" "16=CA" "19=BC" " 6=CB" " 7=ZA"
" 8=AZ" "29=UA" "10=YZ" "18=YW" "12=AK" "13=AJ" "14=HI"
) do for /f "tokens=1,2 delims==" %%a in (%%A) do for %%N in (%%a) do (
set "dev.%%N= %%a"
set "dev.%%b= %%a"
)
call :test 1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA
call :test sadf asdfa
call :test aj 6 13 CB
exit /b
:test
setlocal EnableDelayedExpansion
:: Clear selected
for /f "delims==" %%A in ('set selected. 2^>nul') do set "%%A="
:loadArgs Define a variable for each unique device specified in args
if "%~1" neq "" (
if defined dev.%~1 set "selected.!dev.%~1!=1"
shift /1
goto :loadArgs
)
:: Write out the unique values in sorted order
set "dev= "
for /f "tokens=2 delims== " %%A in ('set selected. 2^>nul') do set "dev=!dev!%%A "
echo selected devices = %dev:~1%
exit /b
- 输出 -
selected devices = 1 2 3 6 7 10 12
selected devices =
selected devices = 6 13
如果您确信用户永远不会在参数中包含*
,?
或)
,那么FOR循环可以替换GOTO循环。 :test
例程简化为以下内容:
:test
setlocal EnableDelayedExpansion
:: Clear selected
for /f "delims==" %%A in ('set selected. 2^>nul') do set "%%A="
:: Define a variable for each unique device specified in args
for %%A in (%*) do if defined dev.%%~A set "selected.!dev.%%~A!=1"
:: Write out the unique values in sorted order
set "dev= "
for /f "tokens=2 delims== " %%A in ('set selected. 2^>nul') do set "dev=!dev!%%A "
echo selected devices = %dev:~1%
exit /b
现在,如果你愿意超越纯天然批次的范围,那么一个班轮肯定是可行的。我会使用我的JSORT.BAT和JREPL.BAT实用程序。 JSORT能够对数字进行排序,因此初始化值中不再需要前导空格。
现在:test
例程确实是一个单一的例子:
@echo off
setlocal
:: Clear devices
for /f "delims==" %%A in ('set dev. 2^>nul') do set "%%A="
:: Define devices
for %%A in (
"1=AB" "2=BA" "3=AC" "16=CA" "19=BC" "6=CB" "7=ZA"
"8=AZ" "29=UA" "10=YZ" "18=YW" "12=AK" "13=AJ" "14=HI"
) do for /f "tokens=1,2 delims== " %%a in (%%A) do (
set "dev.%%a=%%a"
set "dev.%%b=%%a"
)
call :test 1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA
call :test sadf asdfa
call :test aj 6 13 CB
exit /b
:test
(for %%A in (. %*) do @call echo(%%dev.%%A%%) | jsort /n /u | jrepl "(\s|%%.*?%%)+" " " /m | jrepl "^ " ""
exit /b
或
:test
echo(%*|jrepl "(^|\s*)(\S+)" "env('dev.'+$2)" /jmatch | jsort /n /u | jrepl "\s+" " " /m | jrepl "^ " ""
exit /b
答案 1 :(得分:1)
如果您对替代方案持开放态度,请参阅VBScript中的示例(保存在.vbs
扩展名而不是.bat
的文件中):
input = InputBox("", , "1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA")
values = Split(input)
' Adds the values to a sorted list that matches the case
Set list = CreateObject( "System.Collections.Sortedlist" )
For Each value in values
Select Case value
Case "1" , "AB" : list(1 ) = 0
Case "2" , "BA" : list(2 ) = 0
Case "3" , "AC" : list(3 ) = 0
Case "6" , "CB" : list(6 ) = 0
Case "7" , "ZA" : list(7 ) = 0
Case "8" , "AZ" : list(8 ) = 0
Case "10", "YZ" : list(10) = 0
Case "12", "AK" : list(12) = 0
Case "13", "AJ" : list(13) = 0
Case "14", "HT" : list(14) = 0
Case "16", "CA" : list(16) = 0
Case "18", "YW" : list(18) = 0
Case "19", "BC" : list(19) = 0
Case "29", "UA" : list(29) = 0
End Select
Next
' To show the items in the list
For i = 0 To list.Count - 1
output = output & list.GetKey(i) & " "
Next
MsgBox output
另一种选择是PowerShell(扩展名.ps1
):
$s = "1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA"
$a = -split $s
$a = $a -replace "AB", 1
$a = $a -replace "BA", 2
$a = $a -replace "AC", 3
$a = $a -replace "CB", 6
$a = $a -replace "ZA", 7
$a = $a -replace "AZ", 8
$a = $a -replace "YZ", 10
$a = $a -replace "AK", 12
$a = $a -replace "AJ", 13
$a = $a -replace "HT", 14
$a = $a -replace "CA", 16
$a = $a -replace "YW", 18
$a = $a -replace "BC", 19
$a = $a -replace "UA", 29
$a = $a | ? { -split "1 2 3 6 7 8 10 12 13 14 16 18 19 29" -contains $_ }
$l = $a | % { iex $_ }
$l = $l | sort-object -Unique
$l -join " "
但是运行PowerShell脚本有点挑战性,所以你可以从.bat
这样的文件中运行它:
powershell -noprofile -command "&{"^
"$s = '1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA' ;"^
"$a = -split $s ;"^
"$a = $a -replace 'AB', 1 ;"^
"$a = $a -replace 'BA', 2 ;"^
"$a = $a -replace 'AC', 3 ;"^
"$a = $a -replace 'CB', 6 ;"^
"$a = $a -replace 'ZA', 7 ;"^
"$a = $a -replace 'AZ', 8 ;"^
"$a = $a -replace 'YZ', 10 ;"^
"$a = $a -replace 'AK', 12 ;"^
"$a = $a -replace 'AJ', 13 ;"^
"$a = $a -replace 'HT', 14 ;"^
"$a = $a -replace 'CA', 16 ;"^
"$a = $a -replace 'YW', 18 ;"^
"$a = $a -replace 'BC', 19 ;"^
"$a = $a -replace 'UA', 29 ;"^
"$a = $a | ? { -split '1 2 3 6 7 8 10 12 13 14 16 18 19 29' -contains $_ } ;"^
"$l = $a | %% { iex $_ } ;"^
"$l = $l | sort-object -Unique ;"^
"$l -join ' ' ;"^
"}"
pause
答案 2 :(得分:0)
这是一个扩展注释,显示了Dave上面回答中使用的本机Cmd排序的读者的应用程序示例。它需要用零填充编号的变量。
@echo off
setlocal EnableDelayedExpansion
set "devs= 1 10 12 2 3 4 6 7 8 9"
for %%k in (!devs!) do (set /a "devl=100+%%k" & set "devl=!devl:~-2!"
set "dev.!devl!=!devl!")
for /f "tokens=2 delims==" %%l in ('set dev.') do set "devn=!devn! %%l"
echo !devn!
exit /b
:: output
:: 01 02 03 04 06 07 08 09 10 12