Windows batch: Fazendo eco de string não literal contendo caracteres especiais

0

O que eu quero alcançar

Existem algumas URLs em conformidade com um padrão específico. diga

http://example.com/page1.html?arg1=xxx&arg2=yyy
http://example.com/page2.html?arg1=xxx&arg2=yyy
....
http://example.com/page999.html?arg1=xxx&arg2=yyy

Note que há caracteres especiais '&' neles.

Eu gostaria de gerar toda essa lista com o seguinte padrão

http://example.com/page(*).html?arg1=xxx&arg2=yyy

e o (*) substituído pelos números 1,2,...,999 e salve-o em um arquivo (digamos list.txt). Nenhuma cotação em torno dos URLs é permitida.

Meu código e pergunta

Primeiramente eu tentei com esse código:

call :genlist "http://example.com/page(*).html?arg1=xxx&arg2=yyy" 999
exit /b

:genlist
:: given pattern abc(*), generate list abc0, abc1,abc2, ..., abc10, ... abc999 and save them to a file
:: parameters: %1 the pattern.
::             %2 the max number substituting the wildcard

set "patt=%~1"
( for /l %%i in (0,1,%~2) do @echo %patt:(*)=%%i %) >list.txt

exit /b

e falha devido ao caractere meta '&', interpretado como um conector de comando em vez de um caractere normal.

Então tentei a expansão com atraso ativado:

 :genlist
 setlocal enabledelayedexpansion
 set "patt=%~1"
 ( for /l %%i in (0,1,%~2) do @echo !patt:(*)=%%i!) >list.txt
 endlocal
 exit /b 

Isso falha devido a algum erro em torno do %%i!) que eu não entendo.

E pela terceira vez, tentei citar isso:

 :genlist
 setlocal enabledelayedexpansion
 set "patt=%~1"
 ( for /l %%i in (0,1,%~2) do @echo "!patt:(*)=%%i!") >list.txt
 endlocal
 exit /b 

Funciona, mas introduz citações indesejadas no URL.

E eu estou com problemas que o to-be-eco é uma variável, não uma string literal. Se fosse, eu seria capaz de escapar diretamente desse e comercial.

O que devo fazer?

    
por Y.Lin 24.07.2018 / 11:38

1 resposta

0

Finalmente, descobri o problema e resolvi o problema.

Existem alguns caracteres especiais que esqueci de escapar.

!patt:(*)=%%i! deve ser !patt:^(^*^)=%%i! .

Como a expansão atrasada, (0,1,%~2) também deve ser (0^,1^,%~2) .

Então o código deve ser:

:genlist
:: given pattern abc(*), generate list abc0, abc1,abc2, ..., abc10, ... abc999 and save them to a list file
:: parameters: %1 the pattern.
::             %2 the max number substituting the wildcard.

setlocal enabledelayedexpansion
set "patt=%~1"
( for /l %%i in (0^,1^,%~2) do @echo !patt:^(^*^)=%%i! ) >list.txt
endlocal

exit /b

A propósito, escrevi uma parte do código JScript que faz a mesma coisa.

/* JScript: take a pattern of abc(*) and generate a list of abc0,abc1,abc2,...,abc999 
arg1: the pattern
arg2: the max number(not the count)

e.g.  
    cscript /nologo thisscript "http://example.com/page(*).html?arg1=xxx&arg2=yyy" 5

will write to stdout:

http://example.com/page0.html?arg1=xxx&arg2=yyy
http://example.com/page1.html?arg1=xxx&arg2=yyy
http://example.com/page2.html?arg1=xxx&arg2=yyy
http://example.com/page3.html?arg1=xxx&arg2=yyy
http://example.com/page4.html?arg1=xxx&arg2=yyy
http://example.com/page5.html?arg1=xxx&arg2=yyy
*/

with (WScript) {
    var pattern = Arguments.Item(0);
    var max_ind = Arguments.Item(1);

    for (var i=0; i<=max_ind; i+=1)
    {
        Echo (pattern.replace(/\(\*\)/g, i));
    }
}
    
por 24.07.2018 / 16:56

Tags