Windows Пакетный скрипт прекращает чтение файла после записи записи через IF в цикле DO - PullRequest
3 голосов
/ 20 января 2020

Иногда я думаю, что мои отношения с командной строкой Windows взвешены в пользу синдрома Стокгольма, а не муравья. Я надеюсь, что у кого-то еще в этом мире наказаний есть ответ для меня!

Вот предыстория и формулировка проблемы: у меня есть довольно большой скрипт, который работает с for для l oop, который проходит по файлу, ищет номер записи и изменяет запись во время записи записей вокруг хорошим последовательным пакетным способом ie записей записываются в целевую запись; измененная запись записывается; остальные записи написаны. Мне нужно было добавить новый глагол действия к существующему набору, который требует дополнительного предложения IF. Он внезапно перестал записывать оставшиеся записи после того, как найденная запись была изменена. Не удалось найти ответ.

Поэтому я начал убирать код, пока не достиг этого остаточного сценария. Предложение IF в FOR/ in / DO l oop ... Оставьте это, сценарий останавливается после записи, как показано в первом примере ниже; оставьте это, FOR l oop с удовольствием справится со своей задачей, согласно второму примеру вывода. Это становится незнакомым. Добавление в скрипт дает сообщения об ошибках, иногда до конца, иногда даже не простое эхо выдаст ошибку синтаксического анализа. Размещение в сценарии также имеет значение, что делает отладку абсолютным кошмаром.

Очевидно, что что-то заставляет процессор команд выйти из l oop. Поэтому я бы поставил перед сообществом следующие два вопроса:

  1. Что заставляет структуру FOR /in /DO прекратить обработку записей

  2. Что дает с заявлениями эха, дающими ошибки разбора? (отображение имени переменной с номером строки скрипта или, например, только с номером, очень мало влияет.)

Спасибо. Далее следует код, любой текстовый файл можно использовать в качестве второго параметра, первый - номер строки для действия.

echo off
SETLOCAL enabledelayedexpansion

SET _filein=%~2
SET _line=%1
set _cnt=0
:: _filein = any file, _line = the line to be inspected, _cnt = loop counter

:: in the loop: _record = line value, _msg= display message if line is found
FOR /f "tokens=1 delims=" %%i IN ('type %_filein%') DO (
  SET _record=%%i
  SET /a _cnt+=1
  IF [!_cnt!]==[%_line%] (
    echo the line %_line% is !_record!
    set _msg=the line is !_record! at position !_cnt!
    goto sayrecord
  )
  echo not the line:
  :sayrecord
  echo !_cnt!- !_record!
)
:Xit
echo:
IF [%_msg%]==[] (
  echo: left out
) ELSE (
  echo: I'm in to see %_msg%
)

ENDLOCAL
exit /b

Тестовые прогоны:

1. С оператором IF: (примечание об ошибке синтаксического анализа)

H> _a 3 _files.txt

H>echo off
not the line:
1- notes.bat
not the line:
2- notesqa.bat
the line 3 is bulkfiledelete.bat
3- bulkfiledelete.bat

line was unexpected at this time.

H>

Без IF:

H> _a 3 _files.txt

H>echo off
not the line:
1- notes.bat
not the line:
2- notesqa.bat
not the line:
3- bulkfiledelete.bat
not the line:
4- CheckAdminRights.bat
not the line:
 :   :   :
not the line:
47- Reset connection 3 - renew.lnk
not the line:
48- ============

 left out

H>

Ответы [ 2 ]

1 голос
/ 20 января 2020

Учитывая, что ваше заявленное намерение состояло в том, чтобы заменить содержимое %2 в строке %1, вам не нужно отложенное расширение или set для всех этих переменных:

@For /F "Tokens=1*Delims=]" %%I In ('Type "%~2"^|"%__AppDir__%find.exe" /V /N ""')Do @If "%%I"=="[%~1%" (Echo Inserted line content)Else Echo=%%J
@Pause

Вы должны изменить содержимое после Echo и до ) для содержимого строки замены, а последняя строка добавляется только для того, чтобы можно было прочитать вывод.


[Редактировать / ]
Если вы хотите запросить у конечного пользователя подтверждение изменения, прежде чем сделать это, вы можете расширить свой код, включив в него следующее:
@For /F "Tokens=1*Delims=]" %%I In ('Type "%~2"^|"%__AppDir__%find.exe" /V /N ""')Do @If "%%I"=="[%~1" ("%__AppDir__%choice.exe" /M "Replace %%J with new content"&If ErrorLevel 2 (Echo=%%J)Else Echo Inserted line content)Else Echo=%%J
@Pause
1 голос
/ 20 января 2020

ОК, поэтому у меня есть блок кода, который работает благодаря @ jwdonaahue за начальную подсказку; и @ SomethingDark для постановки задачи.

Проблема :label здесь, хотя она работает во многих других производственных скриптах, она явно проблематична c. Вместо сценария, который опускается в конец l oop для обработки, для каждого случая использования необходимо добавить выражение IF.

@echo off
SETLOCAL enabledelayedexpansion

SET _filein=%~2
SET _line=%1
set _cnt=0
:: _filein = any file, _line = the line to be inspected, _cnt = loop counter

:: in the loop: _record = line value, _msg= display message if line is found
FOR /f "tokens=1 delims=" %%i IN ('type %_filein%') DO (
  SET _record=%%i
  SET /a _cnt+=1
  IF [!_cnt!]==[%_line%] (
    echo the line %_line% is !_record!
    set "_msg=the line is !_record! at position !_cnt!"
    echo not the line:
    CALL :sayrecord
  )
  IF [!_cnt!] neq [%_line%] CALL :sayrecord
)
:Xit
echo:
IF [%_msg%]==[] (
  echo: left out
) ELSE (
  echo: I'm in to see %_msg%
)

ENDLOCAL
exit /b

:sayrecord
echo !_cnt!- !_record!
exit /b

, т. Е. Чтобы решить мою проблему,

  1. добавить условие IF для каждого глагола действия;
  2. заканчивается предложением `IF ', которое переносит записи, которые должны быть записаны без изменений

Я также go рассмотрю все сценарии и позабочусь о них!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...