标题: 如何能够实现延迟扩展下的map lookup?
[打印本页]
作者: leson
时间: 2008-9-22 20:21
标题: 如何能够实现延迟扩展下的map lookup?
在一般情形下,可以walkaround实现map的键值查找。
SET key=fri
set map=mon-Monday;tue-Tuesday;wed-Wednesday;thu-Thursday;fri-Friday;sat-Saturday;sun-Sunday
call set value=%%map:*%key%-=%%
set value=%value:;=&rem.%
echo.%value%
但是如何在for循环中实现类似的查找呢?例如当前给出的不是一个键,而是一组键,然后要将它们所对应的值串起来后用。
set "keys=fri mon"
set map=mon-Monday;tue-Tuesday;wed-Wednesday;thu-Thursday;fri-Friday;sat-Saturday;sun-Sunday
set "list="
for %%I in ("%keys: =" "") do (
set "key=%%~I"
call set value=%%map:*!key!-=%%
set value=!value:;=&rem.%
set "list=!list! !value!"
)
echo.%list%
如上尝试,结果不正确,应该是由于变量延迟扩展所引起的,导致每个迭代下的&rem.都不能立刻摔倒,最后list只能获取到第一个匹配值。
希望大家多多指点,谢谢。
作者: HAT
时间: 2008-9-22 22:40
这个是由批处理在进行预处理时符号的优先级决定的:
%%大于
&大于
!!
在未开启变量延迟扩展的时候,先进行变量替换,后处理&符号,所以你的这个方法行得通;开启变量延迟扩展以后,先处理&符号,后进行变量替换,所以你的这个方法就行不通了。
作者: leson
时间: 2008-9-23 06:58
这只是我看到过的一种思路,
请问一般大家都用什么方法实现map的lookup,
直接用set "days.mon=Monday"这种方式我是知道的,
还有其他方法吗?
谢谢。
作者: lxmxn
时间: 2008-9-23 14:05
@echo off & setlocal EnableDelayedExpansion
set "keys=fri mon"
set map=mon-Monday;tue-Tuesday;wed-Wednesday;thu-Thursday;fri-Friday;sat-Saturday;sun-Sunday
set "list="
for %%i in (%keys%) do (
for %%k in (%map%) do (
set str=%%k
if /i "!str:~,3!"=="%%i" set list=!list! !str:~4!
)
)
echo.%list%
作者: leson
时间: 2008-9-23 20:13
楼上的方法挺别致的,
以前我倒不知道;分隔的序列放在for ... in里面也可以遍历的,
而且map lookup,复杂度n^2倒也是可以接受的,
非常感谢。
按照我原来的思路,今天我还是实验出了如何walkaround那个!!、%%、&优先级问题。
方法是通过for转一下,用echo弄掉后面的&rem.,然后再执行直接值set,
想来自我感觉也不错,特分享下。
@echo off
setlocal ENABLEEXTENSIONS
setlocal ENABLEDELAYEDEXPANSION
set "keys=fri mon"
set "map=mon-Monday;tue-Tuesday;wed-Wednesday;thu-Thursday;fri-Friday;sat-Saturday;sun-Sunday"
set "list="
for %%I in ("%keys: =" "%") do (
set "key=%%~I"
call set "value=%%map:*!key!-=%%"
set "value=!value:;=&rem.!"
for /F "delims=" %%A in ('"echo.set value=!value!"') do %%A
set "list=!list! !value!"
)
echo.%list%
作者: leson
时间: 2008-9-23 20:22
顺便说下,我当初遭遇问题的原始需求是,动态生成带序号的目录列表,然后交互时,用户可以输入序号列表,来选择相应的待处理目录。
在始终无法使用&rem.替换方法来实现序号列表和目录列表的映射时,
当初我用到的是一种相对简单直观一点的方法,就是在创建dirs menu的for循环中,
每个迭代中set一个新变量出来,
set /A index=0
for %%I in ("%dirs::=" "%") do (
set "dir=%%~I"
set /A index=!index!+1
echo. !index! !dir!
set "dirs.!index!=!dir!"
)
映射时就相对简单些了,
set "list="
for %%I in (%choices%) do (
set /A "choice=%%~I"
if !choice! GEQ 1 (
if !choice! LEQ %index% (
call set "list=!list!:%%dirs.!choice!%%"
)
)
)
if "%list%"=="" (
echo.None valid choices, try again.
goto :selecting
)
set "dirs=%list:~1%"