пакетный файл с задержкой развертывания построчная копия файла, содержащая восклицательные знаки

Итак, у меня есть два файла, которые содержат идентичный текст, за исключением одной строки, что я делаю, так это копирую отличающуюся строку из файла %source% в файл %target% (что, по сути, просто записывает весь файл построчно в новый файл). Проблема, с которой я сталкиваюсь, заключается в том, что иногда исходный файл будет иметь встроенный комментарий, обозначенный ! который не переводится в целевой файл. Код, который я сейчас запускаю, выглядит следующим образом:

setlocal EnableDelayedExpansion
(
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %source%') do (
set "line=%%b"
if defined line set "line=!line:%replace%=%replaced%!"
echo(!line!
)
) > %target%
endlocal
goto :eof

Для простоты исходный файл представляет собой простой текстовый файл, как и целевой файл. Попробовал пару других "обойти!" проблемы с отложенным расширением, но, похоже, не могу найти тот, который хорошо подходит для этой ситуации, так как я не знаю, где в файле ! произойдет. Я также пытался переместить setlocal/endlocal в цикл for, но это тоже не работает.

Формат любой данной строки в файле %source%, которая может вызвать проблему, будет следующим:

JARG 0.1000 1.2000
LINE 0.5000 1.0000 !This line tells us what is in the line
SMAP 0.0000 1.1100

Спасибо за любую помощь.


person kjg5763    schedule 22.05.2014    source источник


Ответы (1)


Содержимое переменной FOR, содержащее неэкранированный !, всегда будет повреждено, если оно расширяется при включенном отложенном расширении. Это связано с тем, что раскрытие переменной с задержкой происходит после раскрытия переменной FOR.

Хитрость работы с ! в циклах FOR заключается в том, чтобы включать и выключать отложенное раскрытие внутри цикла. Это легко, когда вам не нужно беспокоиться о сохранении присвоений переменных между итерациями, что и происходит в вашей ситуации.

setlocal disableDelayedExpansion
(
  for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %source%') do (
    set "line=%%b"
    setlocal enableDelayedExpansion
    if defined line set "line=!line:%replace%=%replaced%!"
    echo(!line!
    endlocal
  )
) > %target%
endlocal
goto :eof

Явное отключение отложенного расширения вне цикла не требуется, если вы знаете, что оно уже отключено.

person dbenham    schedule 23.05.2014
comment
Хм, я пробовал это двумя разными способами, и однажды у меня были ошибки ограничения расширения с задержкой, а во второй раз он просто работал, как и ожидалось, но удалил файл !. В любом случае, приведенный выше код работает так, как ожидалось, не уверен, что я сделал неправильно раньше, должно быть, мои локальные флаги были в неправильном месте. Благодарю вас! - person kjg5763; 23.05.2014
comment
@ kjg5763 - Заглавная Е не проблема. Пакетные команды не чувствительны к регистру. Я использую смешанный регистр enableDelayedExpansion для удобства чтения. - person dbenham; 23.05.2014