简体   繁体   English

在 DO 循环中通过 IF 写入记录后,Windows 批处理脚本停止读取文件

[英]Windows Batch script stops reading a file after a record has been written via IF in DO loop

Sometimes I think my relationship with the Windows command line is weighted in favour of Stockholms syndrome over anthing else.有时我认为我与 Windows 命令行的关系更倾向于斯德哥尔摩综合症而不是其他。 I'm hoping someone else in this world of punishing stuff has an answer for me!我希望这个惩罚事物的世界上的其他人可以为我解答!

Here's the background and the problem statement: I have a quite large script that does stuff with a for loop that steps through a file searching for a record number, and changing the record while writing the records around in a nice sequential batch way, ie records are written up to the target record;这是背景和问题陈述:我有一个相当大的脚本,它使用 for 循环执行操作,该循环遍历文件搜索记录号,并在以良好的顺序批处理方式写入记录时更改记录,即记录被写入目标记录; a changed record is written;写入更改的记录; the remaining records are written.剩余的记录被写入。 I needed to add a new action verb to the existing set, which requires an additional IF clause.我需要向现有集合添加一个新的动作动词,这需要一个额外的IF子句。 It suddenly stopped writing out remaining records after the found record had been changed.在找到的记录被更改后,它突然停止写出剩余的记录。 Couldn't find the answer.找不到答案。

So I started stripping away code until I reached this residual script.所以我开始剥离代码,直到我到达这个残留的脚本。 The IF clause in the FOR/ in / DO loop ... Leave it in, the script stalls after the written record as per the first sample below; FOR/ in / DO循环中的IF子句...保留它,脚本按照下面的第一个示例在写入记录后停止; leave it out, the FOR loop happily does it's thing, as per the second sample output.忽略它,根据第二个示例输出, FOR循环很高兴地完成了它的工作。 It gets stranger.它变得陌生。 Adding in script gives error messages, sometimes running through to completion, sometimes not ~ even a simple echo will give a parsing error.在脚本中添加会给出错误消息,有时会一直运行到完成,有时不会〜即使是简单的回声也会产生解析错误。 Placement in the script also seems to matter, which made debugging an absolute nightmare.脚本中的位置似乎也很重要,这使得调试成为绝对的噩梦。

Clearly there is something that is triggering the command processor to quit the loop.很明显,有些东西正在触发命令处理器退出循环。 SO I would pose the following two questions to the community:所以我会向社区提出以下两个问题:

  1. What is causing the FOR /in /DO structure to stop processing records是什么导致FOR /in /DO结构停止处理记录

  2. What gives with the echo statements giving parsing errors?给出解析错误的 echo 语句是什么? (echoing a variable name with a script line number, or just the number, for instance, is very low impact. ) (例如,用脚本行号或仅用数字来回应变量名的影响非常小。)

Thanks.谢谢。 Code follows, any text file can be used as the second parameter, the first is a line number to action.代码如下,任何文本文件都可以作为第二个参数,第一个是要操作的行号。

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

Test runs:测试运行:

1. With the IF statement: (note parsing error statement) 1.用IF语句:(注意解析错误语句)

H>_a 3 _files.txt 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>

Without the IF:没有 IF:

H>_a 3 _files.txt 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>

OK, so I have a code block that works thanks to @jwdonaahue for the initial clue;好的,所以我有一个代码块,感谢@jwdonaahue提供了最初的线索; and @SomethingDark for the problem statement.@SomethingDark的问题陈述。

The :label is the problem here, although it works in many other production scripts it clearly is problematic. :label是这里的问题,尽管它可以在许多其他生产脚本中使用,但显然是有问题的。 Instead of a script that drops to the bottom of the loop for processing, putting in an IF clause for each use case is what is needed.不需要放到循环底部进行处理的脚本,而是需要为每个用例放入一个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

ie to solve my problem,即解决我的问题,

  1. add an IF clause for each action verb;为每个动作动词添加一个IF子句;
  2. end with an `IF' clause which wraps the records that must be written unchanged以“IF”子句结尾,该子句包装必须保持不变的记录

I'll also go through all the scripts and do a maint on them!我还将检查所有脚本并对其进行维护!

Given that your stated intent was to replace the content of %2 on line %1 , you don't need delayed expansion or to set all of those variables:鉴于您声明的意图是替换第%1%2的内容,您不需要延迟扩展或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

You would modify the content after Echo and before ) to the replacement line content, and the last line is added just to ensure that you can read the output.您将修改后的内容Echo和前)的替代路线的内容,并添加最后一行只是为了确保您可以读取输出。


[Edit /] [编辑 /]
If you wanted to ask the end user for confirmation of the change before doing so, you could expand your code to incorporate that: 如果您想在这样做之前要求最终用户确认更改,您可以扩展您的代码以合并:

 @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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM