Fuga di caratteri batch

Sono abbastanza abile nello scrivere script di Batch per Windows, ma anche dopo tutti questi anni come sfuggire correttamente i personaggi mi imbarazza. È particolarmente difficile quando si cerca di capire il modo corretto per evitare un’espressione regolare da utilizzare con sed. C’è qualche strumento che può aiutarmi? Forse qualcosa che mi permette di incollare in una stringa “normale” e sputa fuori la versione di escape corretta di quella stringa?

Aggiornamento: Sono riluttante a dare un esempio perché non sto cercando una risposta su come sfuggire a una stringa specifica. Inoltre, non sto cercando una soluzione che funzioni per una specifica app. Sto cercando uno strumento che mi aiuti a ottenere la syntax di escape corretta per ogni stringa che ho sempre bisogno di scappare, indipendentemente dallo strumento che potrebbe utilizzarlo dalla riga di comando.

Detto questo, la regex che voglio davvero è

(^.*)(Form Product=")([^"]*") FormType="[^"]*" FormID="([0-9][0-9]*)".*$ 

Prendi la vera ssed "[email protected] --- Insert escaped regex here --- @http://psph/\1/\[email protected]" "%~1" (cioè senza escape per quanto riguarda BATCH) e avvolgila in qualche syntax sed come ssed "[email protected] --- Insert escaped regex here --- @http://psph/\1/\[email protected]" "%~1" e infine fuggire … Ancora, c’è qualche strumento che può aiutare a sfuggire a qualsiasi stringa per l’uso sulla riga di comando BATCH?

ps Ci sono così tante eccezioni alla syntax di escape di BATCH che mi accontenterò persino di un buon cheat sheet.

Questo è adattato con il permesso dell’autore dalla pagina File batch – Fuga caratteri sul sito di Scripting Pages di Rob van der Woude .

TLDR

L’escape dei caratteri del file batch di Windows (e DOS) è complicato :

Molto simile all’universo, se qualcuno riesce a comprendere pienamente Batch, allora il linguaggio verrà immediatamente sostituito da una versione infinitamente più strana e più complessa di se stessa. Questo è ovviamente successo almeno una volta in precedenza;)

Segno di percentuale

% può essere sfuggito come %% – “Potrebbe non essere sempre richiesto [per essere sfuggito] in stringhe a doppia quotatura, basta provare”

Generalmente, usa un segno di omissione

Questi caratteri “potrebbero non essere sempre richiesti [per essere sfuggiti] in stringhe a doppia quotatura, ma non danneggeranno”:

  • ^
  • &
  • <
  • >
  • |

' è" richiesto [essere sfuggito] solo nel "sobject" FOR /F (cioè tra parentesi), a meno che non backq usato backq "

` è" richiesto [per essere sfuggito] solo nel "sobject" FOR /F (cioè tra parentesi), se viene usato backq "

Questi caratteri sono "richiesti [per essere sfuggiti] solo nel" sobject " FOR /F (cioè tra parentesi), anche nelle stringhe a doppia quota":

  • ,
  • ;
  • =
  • (
  • )

Punti di esclamazione a doppia uscita quando si utilizza l'espansione di una variabile ritardata

! deve essere sfuggito ^^! quando l'espansione variabile ritardata è triggers.

Double Double-Quotes in find Search Patterns

"""

Utilizzare una barra rovesciata nei modelli di findstr Regex

  • \
  • [
  • ]
  • "
  • .
  • *
  • ?

Anche

Rob ha commentato ulteriormente questa domanda (via e-mail di corrispondenza con me stesso):

Per quanto riguarda la risposta, temo che il caos sia anche peggiore di quanto il poster originale comprenda: i requisiti per le parentesi di escape dipendono anche dalla stringa che si trova all'interno di un blocco di codice o no!

Immagino che uno strumento automatizzato potrebbe semplicemente inserire un segno di omissione prima di ogni carattere, quindi raddoppiare tutti i segni di percentuale - e fallirebbe ancora se la stringa è doppiamente quotata!

Inoltre, i singoli programmi sono responsabili dell'analisi dei loro argomenti della riga di comando, pertanto alcune delle operazioni di escape richieste, ad esempio per sed o ssed , potrebbero essere dovute ai programmi specifici richiamati negli script batch.

Il carattere di escape per batch è il caret ( ^ ). Se vuoi includere uno qualsiasi dei personaggi della pipeline nel tuo script devi prefisso il carattere con il cursore:

 :: Won't work: @echo Syntax: MyCommand > [file] :: Will work: @echo Syntax: MyCommand ^> [file] 

Potresti semplicemente usare un file esterno come input per sed.

O usando le stringhe direttamente in batch, è una buona idea usare l’espansione ritardata.

 setlocal DisableDelayedExpansion set "regEx=s/^#*$/""/g" setlocal EnableDelayedExpansion sed !regEx! file.txt 

EDIT: Come utilizzare le stringhe non modificate con un batch

Questo utilizza findstr per ottenere la stringa direttamente dal batch e restituirla in una variabile di risultato.
Quindi puoi usare la stringa sed come è.

 @echo off setlocal REM SedString1#(^.*)(Form Product=")([^"]*") FormType="[^"]*" FormID="([0-9][0-9]*)".*$ call :GetSEDString result SedString1 setLocal EnableDelayedExpansion echo the sedString is !result! sed !result! goto :eof :GetSEDString   :: Search the own batch file for  in a line with "REM #" :: Return all after the "#" without any modification setLocal DisableDelayedExpansion for /f "usebackq tokens=* delims=" %%G in (`findstr /n /c:"REM %~2#" "%~f0"`) do ( set "str=%%G" ) setLocal EnableDelayedExpansion set "str=!str:*#=!" for /F "delims=" %%A in ("!str!") DO ( endlocal endlocal set "%~1=%%A" goto :eof ) goto :eof 

Una semplice soluzione per conservare tutti gli argomenti della riga di comando consiste nell’utilizzare %* : restituisce l’intera riga di comando a partire dal primo argomento della riga di comando (in Windows NT 4, %* include anche tutti gli spazi iniziali) ed esclude qualsiasi reindirizzamento dell’output.