2015-11-30 10 views
5

Capisco che in un file batch di Windows, %* espande a tutti gli argomenti della riga di comando, e che shift turni gli argomenti della riga di comando numerati %1, %2, ecc, ma che non modificare il contenuto di %*.usando `% *` `dopo shift`

Cosa devo fare se voglio una versione di %* che fa riflettono l'effetto di shift? Capisco che potrei semplicemente dire %1 %2 %3 %4 %5 %6 %7 %8 %9 dopo aver cambiato, ma sembra stupido e potenzialmente pericoloso che mi limita ad un numero fisso di argomenti.

Anche se questa non è una domanda specifica per Python, può aiutare a capire che la ragione per cui voglio questo comportamento è che ho dovuto scrivere un file batch SelectPython.bat che preconfigura determinate variabili d'ambiente, per navigare la babele di diverse distribuzioni Python che ho (devi impostare %PYTHONHOME%, %PYTHONPATH% e %PATH% in determinati modi prima di poter chiamare il binario di Python e avere la certezza che otterrai la giusta distribuzione). Il mio script corrente funziona bene per impostare queste variabili, ma vorrei essere in grado di chiamare e Python in una sola riga - ad esempio:

SelectPython C:\Python35 pythonw.exe myscript.py arg1 arg2 arg3 ... 

Idealmente voglio che il mio file batch per usare shift di "mangiare" il primo argomento, lo elabora di conseguenza e imposta l'ambiente, quindi esegue automaticamente in modo automatico la stringa formata dal resto degli argomenti. Il principio è analogo al modo in cui env avvolge i comandi nei sistemi POSIX:

env FOO=1 echo $FOO  # wrap the `echo` command to be executed in the context of specified environment settings 

Finora ho questo - l'ultima riga è dove il problema è:

@echo off 
set "LOC=%CD% 
if not "%~1" == "" set "LOC=%~1 
if exist "%LOC%\python.exe" goto :Success 

echo "python.exe not found in %LOC%" 
goto :eof 

:Success 
:: Canonicalize the resulting path: 
pushd %LOC% 
set "LOC=%CD% 
popd 

:: Let Python know where its own files are: 
set "PYTHONHOME=%LOC% 
set "PYTHONPATH=%LOC%;%LOC%\Lib\site-packages 

:: Put Python's location at the beginning of the system path if it's not there already: 
echo "%PATH%" | findstr /i /b /c:"%PYTHONHOME%" > nul || set "PATH=%PYTHONHOME%;%PYTHONHOME%\Scripts;%PATH% 

:: Now execute the rest: 
shift 
if "%~1" == "" goto :eof 
%1 %2 %3 %4 %5 %6 %7 %8 %9 
:: This is unsatsifactory - what if there are more than 9 arguments? 

UPDATE: Grazie a Stephan la mia soluzione di lavoro ora ha la seguente sezione modificata:

:: Now execute the rest of the arguments, if any: 
shift 
if @%1 == @ goto :eof 
set command= 
:BuildCommand 
if @%1 == @ goto :CommandFinished 
set "command=%command% %1" 
shift 
goto :BuildCommand 
:CommandFinished 
%command% 
+1

Impossibile assegnare tutti gli argomenti a una variabile, quindi utilizzare la sostituzione di stringhe per rimuovere il primo. – Squashman

+0

Hmm, sembra una potenziale via da seguire. Ma senza il potere delle regex corrette, non sono sicuro che saprei come gestire potenziali citazioni e spazi in modo appropriato con questo approccio. Funzionerebbe per 'SelectPython" C: \ Program Files \ Oh dio perché l'ho installato qui \ Python27 "python -c" print 'hello' "'? – jez

risposta

2

creare il proprio "% *" (Ho chiamato %params%):

set "params=" 
:build 
if @%[email protected] goto :cont 
shift 
set "params=%params% %1" 
goto :build 
:cont 
echo params are %params% 
+0

Questo ha funzionato abbastanza bene per me. L'unica cosa che non gestisce è un argomento a stringa vuota e tutto ciò che lo segue. Ad esempio, 'python -c" importa sys; print (repr (sys.argv [1:])) "" "" "' riceve e stampa correttamente i suoi due argomenti a stringa vuota. Quando viene filtrato attraverso questo test, non riceve nulla dopo la prima stringa vuota. Riesci a pensare a un modo per gestirlo? – jez

+0

Vedere la mia modifica. (che era troppo facile - sono abbastanza sicuro, ho perso qualcosa ...) – Stephan

+0

OK, ha funzionato. Non sono sicuro del motivo per cui ha funzionato: in alcune circostanze ho visto 'if% 1 == something' fallire con un errore di sintassi quando'% 1' contiene uno spazio, eppure questo sembra sopravvivere a quell'eventualità. Ad ogni modo, ora penso che tutte le basi siano coperte - molte grazie! – jez

1

Il codice del lotto secondo l'idea di Squashman

@echo off 
setlocal EnableDelayedExpansion 
set "LOC=%1" 
set "AllParameters=%*" 
set "AllButFirst=!AllParameters:%LOC% =!" 
echo Remaining: %AllButFirst% 
endlocal 
pause 

Questo produce per

"C:\Program Files\Oh god why did I install it here\Python27" python -c "print 'hello'" 

l'output previsto

python -c "print 'hello'" 

Problema con questo codice: se il percorso della directory (primo pararametro) viene trovato anche su un altro parametro, viene rimosso anche dall'altro parametro perché la sostituzione rimuove tutte le occorrenze della stringa cercata e non solo la prima occorrenza.

+0

Sì. Questo è quello che stavo pensando. Potresti anche sbarazzarti dell'espansione ritardata e usare 'call set AllButFirst = %% AllParameters:% LOC% = %%' – Squashman

2

Solo una leggera variazione dall'esempio di Mofi ma protegge dalla rimozione di qualsiasi argomento aggiuntivo utilizzando il nome del file batch come parte di tutti gli argomenti e quindi rimuove il file batch e l'argomento 1.

@echo off 
set all_args=%~f0%* 
call set exe_arg=%%all_args:%~f0%1 =%% 
echo %exe_arg% 
pause 

In definitiva però, se si vuole risparmiare qualche secondo Centi utilizzando espansione ritardata è più veloce quindi utilizzando CALL o usando SHIFT.

@echo off 
setlocal enabledelayedexpansion 
set all_args=%~f0%* 
set exe_arg=!all_args:%~f0%1 =! 
echo %exe_arg% 
+0

... o suppongo che potresti usare qualsiasi altro "sale" che pensi sia improbabile che si verifichi in il selvaggio, invece di '% 0' – jez

+0

@jez, suppongo di sì, ma le probabilità che lo script abbia il nome del file batch e l'argomento 1 combinati insieme senza spazio come altro argomento sono probabilmente da zero a nessuno. Probabilmente renderebbe ancora più infallibile l'uso di '% ~ f0' – Squashman

+0

@jez, o semplicemente usare un numero casuale. 'set rnd =% random %% random%' – Squashman

Problemi correlati