Batch - заменить строку в текстовом файле, используя цикл for, включая пустые строки - PullRequest
0 голосов
/ 04 апреля 2019

Я нашел ответ Джеба, который копирует файл в другой файл, включая пустые строки, добавив число: в начале каждой строки -

(
set taglinelinks=one two three
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ overview.md"`) do (
    set "var=%%a"
    if "%var:~0,2%" == "5:" (echo %taglinelinks%)
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo(!var!
)
) > new.txt

Я добавил переменную вверху для тестирования и добавил строку «если». Он работает хорошо без строки «если», но я не вижу ничего плохого в этой строке. Я проверяю, является ли номер строки 5, и если она выводит переменную в файл, то продолжаю. У меня должна быть команда else в моем операторе if, но сейчас я не могу определить, что поместить туда, чтобы остальная часть кода не пропускала исходное содержимое строки 5.

Ответы [ 2 ]

2 голосов
/ 05 апреля 2019

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

В любом случае, сначала я хочу показать адаптированный и рабочий код:

@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-разрядное целое число со знаком. Если результат не может быть представлен как таковой, он становится принудительным.

1 голос
/ 05 апреля 2019

Вы можете попробовать это так:

@Echo Off
Set "taglinelinks=one two three"
(   For /F "Tokens=1*Delims=:" %%A in ('Findstr /N "^" "overview.md"')Do (
        If %%A NEq 5 (Echo=%%B)Else Echo %taglinelinks%
    )
)>"new.txt"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...