Сбой группового символа
Я достаточно разбираюсь в написании Batch-скриптов для 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?
p.s. Существует так много исключений из синтаксиса BATCH, что я даже соглашусь на хороший чит-лист.
Ответы
Ответ 1
Это адаптировано с разрешения автора со страницы Пакетные файлы - символы побега на сайте сценариев Роба ван дер Вуде.
TLDR
Экранирование символов командного файла в Windows (и DOS) является сложным:
Как и во вселенной, если кто-то когда-либо полностью поймет Пакет, тогда язык будет немедленно заменен бесконечно более странной и более сложной версией самого себя. Это, очевидно, произошло, по крайней мере, один раз раньше;)
Знак процента %
%
можно экранировать как %%
- "Может не всегда требоваться [экранироваться] в строках в двойных кавычках, просто попробуйте"
Как правило, используйте каретку ^
Эти символы "не всегда могут потребоваться [экранироваться] в строках в двойных кавычках, но это не повредит":
Пример: echo a ^> b
для печати a > b
на экране
'
"требуется [должен быть экранирован] только в FOR /F
" субъекте "(то есть между круглыми скобками), , если не используется backq
"
'
"требуется [должен быть экранирован] только в FOR /F
" субъекте "(то есть между круглыми скобками), , если backq
используется"
Эти символы "обязательны [для экранирования] только в FOR /F
" субъекте "(то есть между круглыми скобками), даже в строках в двойных кавычках":
Восклицательные знаки Double Escape при использовании отложенного расширения переменной
!
должен быть экранирован ^^!
, когда активировано отложенное расширение переменной.
Двойные двойные кавычки в find
шаблонах поиска
"
→ ""
Используйте обратную косую черту в findstr
шаблонах регулярных выражений
Также
Роб прокомментировал этот вопрос далее (через электронную переписку со мной):
Что касается ответа, я боюсь, что хаос еще хуже, чем понимает оригинальный плакат: требования к экранированию скобок также зависят от того, находится строка внутри блока кода или нет!
Я полагаю, что автоматизированный инструмент может просто вставить знак вставки перед каждым символом, а затем удвоить все знаки процента - и он все равно потерпит неудачу, если строка будет заключена в двойные кавычки!
Кроме того, отдельные программы отвечают за синтаксический анализ своих аргументов командной строки, поэтому некоторые из экранирования требуются, например, для: для sed
или ssed
может быть связано с конкретными программами, вызываемыми в пакетных сценариях.
Ответ 2
Эквивалентным символом для партии является карет (^
). Если вы хотите включить любой из символов конвейера в свой script, вам нужно префикс символа с помощью каретки:
:: Won't work:
@echo Syntax: MyCommand > [file]
:: Will work:
@echo Syntax: MyCommand ^> [file]
Ответ 3
Вы можете просто использовать внешний файл для ввода sed.
Или используя строки непосредственно в пакетном режиме, рекомендуется использовать задержанное расширение.
setlocal DisableDelayedExpansion
set "regEx=s/^#*$/""/g"
setlocal EnableDelayedExpansion
sed !regEx! file.txt
EDIT: использование немодифицированных строк с пакетом
Это использует findstr, чтобы получить строку непосредственно из пакета и вернуть ее в переменную result.
Таким образом, вы можете использовать sed-строку как есть.
@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
Ответ 4
Простым решением для сохранения всех аргументов командной строки является использование %*
: он возвращает всю командную строку, начинающуюся с первого аргумента командной строки (в Windows NT 4, %*
также включает все ведущие пробелы) и исключая любое перенаправление вывода.