it-swarm.com.ru

Пакетный персонаж убегает

Я довольно опытный в написании пакетных скриптов для Windows, но даже после всех этих лет, как правильно экранировать персонажей, озадачивает меня. Это особенно трудно при попытке найти правильный способ избежать регулярного выражения для использования с sed. Есть ли инструмент, который может мне помочь? Возможно, что-то, что позволяет мне вставить «нормальную» строку, и оно выплевывает правильно экранированную версию этой строки?

Обновление: Я не хочу приводить пример, потому что я не ищу ответ о том, как избежать одной конкретной строки. Я также не ищу решение, которое будет работать для одного конкретного приложения. Я ищу инструмент, который поможет мне получить правильный синтаксис escape для каждой строки, которую мне когда-либо нужно экранировать, независимо от того, какой инструмент использует его из командной строки. 

Это, как говорится, регулярное выражение, которое я действительно хочу, 

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

Возьмите это истинное регулярное выражение (т. Е. Не экранированный в отношении BATCH) и оберните его в некоторый синтаксис sed, такой как ssed "[email protected] --- Insert escaped regex here --- @http://psph/\1/\[email protected]" "%~1", и, наконец, экранируйте его ... Опять же, есть ли инструмент, который может помочь в экранировании любой строки для использования в команде BATCH линия? 

постскриптум Существует так много исключений из исключающего синтаксиса BATCH, что я даже остановлюсь на хорошей шпаргалке.

30
HairOfTheDog

Это адаптировано с разрешения автора со страницы Пакетные файлы - Escape-персонажи on Сайт сценариев Роба ван дер Вуде .

TLDR

Экранирование символов пакетного файла в Windows (и DOS) является сложным :

Как и во вселенной, если кто-то когда-либо сделает полностью поймет Пакет, тогда язык будет немедленно заменен бесконечно более странной и более сложной версией самого себя. Это, очевидно, произошло, по крайней мере, один раз раньше;)

Знак процента

% может быть экранирован как %% - «Может не всегда требоваться [быть экранированным] в строках в двойных кавычках, просто попробуйте»

Как правило, используйте каретку

Эти символы «не всегда могут потребоваться [экранироваться] в строках в двойных кавычках, но это не повредит»:

  • ^
  • &
  • <
  • >
  • |

' "требуется [для экранирования] только в FOR /F" субъекте "(то есть между круглыми скобками), еслиbackq не используется"

` "требуется [для экранирования] только в FOR /F" субъекте "(т. е. в скобках), ifbackq используется"

Эти символы «обязательны [для экранирования] только в FOR /F« теме »(то есть между скобками), даже в строках в двойных кавычках»:

  • ,
  • ;
  • =
  • (
  • )

Восклицательный знак Double Escape при использовании отложенного расширения переменной

! должен быть экранирован ^^!, когда активна задержка расширения переменной.

Двойные двойные кавычки в find Шаблоны поиска

"""

Используйте обратную косую черту в findstr шаблонах регулярных выражений

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

Также

Далее Роб прокомментировал этот вопрос (через электронную переписку со мной):

Что касается ответа, я боюсь, что хаос еще хуже, чем понимает оригинальный плакат: требования к экранированию скобок также зависят от того, находится строка внутри блока кода или нет!

Я предполагаю, что автоматизированный инструмент мог бы просто вставить каретку перед каждым символом, а затем удвоить все знаки процента - и все равно не получится, если строка будет заключена в двойные кавычки!

Кроме того, отдельные программы отвечают за синтаксический анализ своих аргументов командной строки, поэтому некоторые из экранирования требуются, например, для: для sed или ssed может быть связано с конкретными программами, вызываемыми в пакетных сценариях.

44
Kenny Evitt

Экранирующим символом для пакета является символ каретки (^). Если вы хотите включить какой-либо из символов конвейера в ваш скрипт, вам нужно добавить префикс перед символом:

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

:: Will work:
@echo Syntax: MyCommand ^> [file]
5
Patrick Cuff

Вы можете просто использовать внешний файл в качестве входных данных для sed. 

Или используя строки непосредственно в пакетном режиме, рекомендуется использовать отложенное расширение.

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

Правка: Как использовать неизмененные строки с пакетом

Это использует findstr, чтобы получить строку непосредственно из пакета и вернуть ее в переменную результата.
Таким образом, вы можете использовать sed-string как есть.

@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 <resultVar> <searchName>
:: Search the own batch file for <searchName> in a line with "REM <searchName>#"
:: 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
1
jeb

Простым решением для сохранения всех аргументов командной строки является использование %*: он возвращает всю командную строку, начиная с первого аргумента командной строки (в Windows NT 4, %* также включает все начальные пробелы) и исключая любое перенаправление вывода.

0
Pino