在批处理参数数组中筛选重复项

sam*_*l35 0 cmd batch-file filter

我正在编写一个批处理,用户必须输入一个设备列表才能作为批处理参数激活.该列表可以包含随机顺序的设备号和/或名称以及可能的重复和残留物(即,不存在或不存在就绪设备).batch :default部分以随机顺序存储数组dev _#=所有当前Ready设备的名称.初始任务是过滤用户输入以排除重复项和残留项,并显示要激活的已排序的准备好的设备号列表.然后激活该列表中的设备.什么样的高效短代码可以完成过滤任务?

@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
Run Code Online (Sandbox Code Playgroud)

dbe*_*ham 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
Run Code Online (Sandbox Code Playgroud)

--OUTPUT--

selected devices = 1 2 3 6 7 10 12
selected devices =
selected devices = 6 13
Run Code Online (Sandbox Code Playgroud)

如果您确信用户永远不会包含*,?)在参数内,那么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
Run Code Online (Sandbox Code Playgroud)

现在,如果你愿意超越纯天然批次的范围,那么一个班轮肯定是可行的.我会使用我的JSORT.BATJREPL.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
Run Code Online (Sandbox Code Playgroud)

要么

:test
echo(%*|jrepl "(^|\s*)(\S+)" "env('dev.'+$2)" /jmatch | jsort /n /u | jrepl "\s+" " " /m | jrepl "^ " ""
exit /b
Run Code Online (Sandbox Code Playgroud)