В этом ответе я придерживаюсь нашего исходного кода и фокусируюсь на недостатках. В основном мне нравится этот подход (с исправленными ошибками, конечно), потому что он может даже правильно обрабатывать строки, начинающиеся с двоеточия :
, и у него нет никаких проблем с появлением !
в текстовом файле с задержкой расширения переключается.
В любом случае, сначала я хочу показать адаптированный и рабочий код:
@echo off
setlocal DisableDelayedExpansion
set "taglinelinks=one two three"
> "new.txt" (
for /F "delims=" %%a in ('findstr /N "^" "overview.md"') do (
set "var=%%a"
setlocal EnableDelayedExpansion
if "!var:~,2!" == "5:" (
echo(!taglinelinks!
) else (
echo(!var:*:=!
)
endlocal
)
)
endlocal
И вот что я исправил:
- предложение
if
должно находиться в блоке с включенным отложенным расширением, поэтому я переместил его на одну строку вниз и изменил %
на !
;
- Я реализовал предложение
else
, чтобы оно содержало оставшуюся часть кода в теле цикла for /F
- Я добавил отсутствующий
endlocal
, поэтому вы не можете столкнуться с setlocal
ограничениями вложенности, и командная строка set "var=%%a"
фактически появляется в разделе кода с отключенным отложенным расширением, что необходимо, чтобы не вызывать проблем с !
появляется в файле;
А вот некоторые незначительные и косметические изменения:
- Я добавил
@echo off
сверху, чтобы избежать ввода командных эхо в new.txt
;
- Я переместил начальную команду
setlocal
вверх, чтобы сначала отключить отложенное расширение, чтобы !
можно было даже безопасно использовать в перенаправленном имени файла и в первой командной строке set
(так как мы не можем знать, было ли отложенное расширение отключено или включено ранее);
- Я использовал цитируемый синтаксис
set
также для присвоения переменной taglinelinks
, чтобы сделать ее безопасной; затем я переместил эту строку за пределы блока перенаправления, чтобы стать более очевидным;
- хотя это и не мешает, опция
usebackq
не нужна, поэтому я удалил ее и использовал одиночные кавычки ''
(но это просто вопрос вкуса);
- цитируемая
findstr
командная строка выглядит немного странно, особенно экранированный символ ^^
, поэтому я изменил кавычку так, чтобы строка поиска и путь к файлу были заключены в кавычки, поэтому такое экранирование больше не требуется, и имя файла может даже содержать пробелы или другие специальные символы;
- строка для отображения значения
taglinelinks
находится не в блоке, где включено отложенное расширение; это позволяет переменной содержать даже специальные символы;
- второе назначение
set "var=!var:*:=!"
на самом деле не нужно, поэтому я удалил его и немедленно повторил усеченную строку;
- Я адаптировал отступ кода, также для блока
if
/ else
, чтобы улучшить читаемость;
- Я переместил перенаправление
> "new.txt"
в начало внешнего блока, заключенного в скобки, чтобы сделать его более заметным (но это опять-таки просто вопрос вкуса), и я поставил двойные кавычки вокруг имени файла, чтобы оно могло даже содержать пробелы или другие специальные символы;
- Я добавил еще одну явную команду
endlocal
, которая принадлежит исходной setlocal
;
В скрипте есть еще одна вещь, которая мне не нравится, а именно: негибкий способ определения номера текущей строки, поскольку в настоящее время он работает только для чисел, меньших 10
, без небольшой адаптации кода.
Вот способ гибко указать номер строки для замены:
@echo off
setlocal DisableDelayedExpansion
set "taglinelinks=one two three"
set "linenumber=5"
> "new.txt" (
for /F "delims=" %%a in ('findstr /N "^" "overview.md"') do (
set "var=%%a"
setlocal EnableDelayedExpansion
set /A "num=var"
if !num! equ !linenumber! (
echo(!taglinelinks!
) else (
echo(!var:*:=!
)
endlocal
)
)
endlocal
Вот что я сделал:
- сначала я определил переменную (константу)
linenumber
с номером строки 5
; учтите, что linenumber
не должно содержать начальных нулей, чтобы число, которое не было интерпретировано как восьмеричное целое позже (if
);
- в цикле, который я поместил
set /A "num=var"
, который использует неявное расширение переменной set /A
, что означает, что строка строки сканируется слева направо до первого нечислового символа 1 затем эта строка преобразуется в целое число и, наконец, присваивается num
; это означает, что файл содержит менее 2 31 строк; - предложение
if
изменено на if !num! equ !linenumber!
, которое выполняет числовое сравнение из-за equ
, поскольку оба выражения являются целыми числами; так что это больше не зависит от количества цифр номера строки; здесь я также мог бы использовать %linenumber%
, так как переменная не изменялась в блоке кода, но я решил использовать !linenumber!
, чтобы охватить случай неправильной инициализации этой переменной (особенно когда она пустая или содержит специальные символы из-за опечаток);
1) Фактически ведущие ПРОБЕЛЫ и TAB игнорируются. Далее может появиться одиночный знак +
или -
. Затем все до следующего нечислового числа используется для преобразования строки в 32-разрядное целое число со знаком. Если результат не может быть представлен как таковой, он становится принудительным.