繁体   English   中英

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

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

有时我认为我与 Windows 命令行的关系更倾向于斯德哥尔摩综合症而不是其他。 我希望这个惩罚事物的世界上的其他人可以为我解答!

这是背景和问题陈述:我有一个相当大的脚本,它使用 for 循环执行操作,该循环遍历文件搜索记录号,并在以良好的顺序批处理方式写入记录时更改记录,即记录被写入目标记录; 写入更改的记录; 剩余的记录被写入。 我需要向现有集合添加一个新的动作动词,这需要一个额外的IF子句。 在找到的记录被更改后,它突然停止写出剩余的记录。 找不到答案。

所以我开始剥离代码,直到我到达这个残留的脚本。 FOR/ in / DO循环中的IF子句...保留它,脚本按照下面的第一个示例在写入记录后停止; 忽略它,根据第二个示例输出, FOR循环很高兴地完成了它的工作。 它变得陌生。 在脚本中添加会给出错误消息,有时会一直运行到完成,有时不会〜即使是简单的回声也会产生解析错误。 脚本中的位置似乎也很重要,这使得调试成为绝对的噩梦。

很明显,有些东西正在触发命令处理器退出循环。 所以我会向社区提出以下两个问题:

  1. 是什么导致FOR /in /DO结构停止处理记录

  2. 给出解析错误的 echo 语句是什么? (例如,用脚本行号或仅用数字来回应变量名的影响非常小。)

谢谢。 代码如下,任何文本文件都可以作为第二个参数,第一个是要操作的行号。

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>

好的,所以我有一个代码块,感谢@jwdonaahue提供了最初的线索; @SomethingDark的问题陈述。

:label是这里的问题,尽管它可以在许多其他生产脚本中使用,但显然是有问题的。 不需要放到循环底部进行处理的脚本,而是需要为每个用例放入一个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”子句结尾,该子句包装必须保持不变的记录

我还将检查所有脚本并对其进行维护!

鉴于您声明的意图是替换第%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

您将修改后的内容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

暂无
暂无

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

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