Batch character escaping

Soy bastante hábil en escribir guiones por lotes para Windows, pero incluso después de todos estos años, cómo escapar correctamente de los personajes me desconcierta. Es especialmente difícil cuando intentas encontrar la forma correcta de escapar de una expresión regular para usar con sed. ¿Hay alguna herramienta que pueda ayudarme? ¿Quizás algo que me permite pegar una cadena “normal” y escupe la versión correctamente escapada de esa cadena?

Actualización: soy reacio a dar un ejemplo porque no estoy buscando una respuesta sobre cómo escapar de una cadena específica. Tampoco estoy buscando una solución que funcione para una aplicación específica. Estoy buscando una herramienta que me ayude a obtener la syntax de escape correcta para cada cadena que necesite escapar, sin importar qué herramienta pueda estar consumiéndola desde la línea de comandos.

Dicho esto, la expresión regular que realmente quiero es

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

Toma esa expresión regular verdadera (es decir, no guardada en lo que respecta a BATCH) y envuélvela en una syntax sed como ssed "s@ --- Insert escaped regex here --- @http://psph/\1/\2@g" "%~1" y finalmente lo escapo … De nuevo, ¿hay alguna herramienta que pueda ayudar a escapar cualquier cadena para usar en la línea de comando BATCH?

ps Hay tantas excepciones a la syntax de escape de BATCH que incluso me conformaré con una buena hoja de trucos.

Esto se adapta con permiso del autor de la página Batch files – Escape Characters en el sitio de Scripting Pages de Rob van der Woude .

TLDR

El escape del carácter del archivo por lotes de Windows (y DOS) es complicado :

Al igual que el universo, si alguien llega a comprender por completo Batch, el lenguaje será instantáneamente reemplazado por una versión de sí misma infinitamente más extraña y compleja. Esto obviamente ha sucedido al menos una vez antes;)

Signo de porcentaje

% se puede escapar como %% – “Puede que no siempre se requiera [que se escape] en cadenas de dobles comillas, solo inténtalo”

En general, use un Caret

Es posible que estos caracteres “no siempre se requieran [se escapen] en cadenas de dobles comillas, pero no dolerá”:

  • ^
  • &
  • <
  • >
  • |

' es "obligatorio [para ser escapado] solo en el FOR /F " sujeto "(es decir, entre paréntesis), a menos que se use backq

` is" required [to be escape] only en FOR /F "subject" (es decir, entre paréntesis), si backq se usa "

Estos caracteres son "obligatorios [para escaparse] solo en FOR /F " subject "(es decir, entre paréntesis), incluso en cadenas dobles":

  • ,
  • ;
  • =
  • (
  • )

Puntos de exclamación de doble escape cuando se usa la expansión variable diferida

! debe ser escapado ^^! cuando la expansión variable diferida está activa.

Double Double-Quotes en find Search Patterns

"""

Use una barra findstr en los findstr expresiones findstr findstr

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

también

Rob comentó más sobre esta pregunta (por correo electrónico conmigo mismo):

En cuanto a la respuesta, me temo que el caos es aún peor de lo que el cartel original se da cuenta: los requisitos para escaparse paréntesis también dependen de que la cadena esté dentro de un bloque de código o no.

Supongo que una herramienta automatizada podría simplemente insertar un símbolo de intercalación antes de cada carácter, y luego doblar todos los signos de porcentaje, ¡y aún así fallaría si la cadena tuviera una doble cita!

Además, los progtwigs individuales son responsables de analizar sus argumentos de línea de comando, por lo que parte del escape requerido, por ejemplo, sed o ssed , puede deberse a los progtwigs específicos llamados en los scripts por lotes.

El carácter de escape para el lote es el símbolo de intercalación ( ^ ). Si desea incluir cualquiera de los caracteres de interconexión en su secuencia de comandos, debe agregar el carácter al prefijo:

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

Simplemente podría usar un archivo externo como entrada para sed.

O usando cadenas directamente en lote, es una buena idea usar la expansión demorada.

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

EDITAR: Cómo usar cadenas sin modificar con un lote

Esto usa findstr para obtener la cadena directamente del lote y devolverla a una variable de resultado.
Entonces puedes usar el sed-string como está.

 @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 solución simple para conservar todos los argumentos de línea de comando es usar %* : devuelve toda la línea de comando comenzando en el primer argumento de línea de comando (en Windows NT 4, %* también incluye todos los espacios iniciales) y excluye cualquier redirección de salida.