簡體   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