簡體   English   中英

Windows 命令在 cmd 但不是 .bat 文件中工作

[英]Windows command working in cmd but not .bat file

我正在嘗試替換某些文件中的一行(基於文件擴展名)。 該程序未按預期運行,導致問題的命令是以下命令。

FOR /F %%k IN ('TYPE !FILE! ^| FINDSTR /N "^"') DO (

這會返回以下錯誤:

FINDSTR: No search strings 該進程試圖寫入一個不存在的 pipe。

但是,在命令行中運行時,命令本身會按預期工作。 我已經花了將近一整天的時間,但無濟於事。 FOR /F %k IN ('TYPE <filename> ^| FINDSTR /N "^"') DO echo(%k

指針將不勝感激!

下面提供了完整的代碼以供參考。

@echo off
CD data
FOR /F "delims=" %%i IN ('DIR *.ext1 /B') DO (
  SET "FILE=%%i"
  SETLOCAL EnableDelayedExpansion
  echo(!FILE!
  <!FILE! >!FILE!.tmp~ (
    REM Find line number on which Logon command is found
    FOR /F "tokens=1,* delims=: " %%j IN ('FINDSTR /I /N /R "^\.LOGON.*" !FILE!') DO (
      SET "NUM=%%j"
    )
    REM Print all lines along with line number at beginning
    FOR /F %%k IN ('TYPE !FILE! ^| FINDSTR /N "^"') DO (
      SET "LINE=%%k"
      REM Replace entire content of Logon line with Run file command
      FOR /F "tokens=1,* delims=:" %%l IN ("!LINE!") DO IF %%l EQU !NUM! (
        echo(.RUN FILE logon.txt;
      ) ELSE (
        echo(!LINE:*:=!
      )
    )
  )
  MOVE /Y "!FILE!.tmp~" !%FILE!"
  ENDLOCAL
)
CD ..

FOR /F %%k IN ('TYPE !FILE! ^| FINDSTR /N "^"') DO (行中的問題是您啟用了延遲變量擴展,這也消耗了插入符號^ escaping 即使在被引用的情況下。詳情另請參閱此帖子: Windows 命令解釋器(CMD.EXE)如何解析腳本?

要解決此問題,您只需將插入符號加倍:

FOR /F %%k IN ('TYPE !FILE! ^| FINDSTR /N "^^"') DO (

請注意,將$指定為findstr的搜索字符串會跳過輸入數據的最后一行,以防它沒有被換行符終止。 另請注意, $錨定回車符,它僅存在於帶有 Windows 樣式的行尾標記回車加換行符的文本文件中。


無論如何,這是您的代碼的固定變體,它盡可能避免延遲擴展,因此實際上不需要加倍插入符號:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // It is assumed here that the parent directory of the script is the root location:
pushd "%~dp0data" && (
    for /F "delims=" %%I in ('dir /B /A:-D-H-S "*.ext1"') do (
        set "FILE=%%I"
        echo(%%I
        rem // Here `%%I` is used instead of `!FILE!` since delayed expansion is disabled:
        < "%%I" > "%%I.tmp~" (
            rem // Use right word boundary `\>` in the search string:
            for /F "tokens=1,* delims=:" %%J in ('findstr /I /N /R "^\.LOGON\>" "%%I"') do (
                rem /* Since this loop should iterate once only anyway, the interim variable
                rem    `NUM` is actually not really needed when the remaining code is also
                rem    placed within the loop body: */
                rem set "NUM=%%J"
                rem // At this point delayed expansion is still disabled:
                for /F %%K in ('type "%%I" ^| findstr /N "^"') do (
                    set "LINE=%%K"
                    rem // Here `%%J` is used instead of `!NUM!`:
                    for /F "tokens=1,* delims=:" %%L in ("!LINE!") do if %%L equ %%J (
                        echo(.RUN FILE logon.txt;
                    ) else (
                        rem // This is the only part where delayed expansion is needed:
                        setlocal EnableDelayedExpansion
                        echo(!LINE:*:=!
                        endlocal
                    )
                )
            )
        )
        > nul move /Y "%%I.tmp~" "%%I"
    )
    popd
)

endlocal
exit /B
只要您的源運行文件沒有任何以:字符開頭的行,以下內容可能會提供另一種執行任務的方法:
 @%__AppDir__%where.exe /Q "data":"*.mload" >NUL 2>&1 && (CD "data" For /F "EOL=? Delims=" %%H In ( '%__AppDir__%findstr.exe /IM "\<\.LOGON\>" "*.mload" 2^>NUL' ) Do @(Copy /Y "%%H" "%%~nH.tmp~" >NUL && ( For /F "Tokens=1,* Delims=:" %%I In ( '%__AppDir__%findstr.exe /N "^" "%%~nH.tmp~"' ) Do @Set /P "=:%%J"<NUL|%__AppDir__%findstr.exe /LIB ":.LOGON " >NUL && ( Echo.RUN FILE logon.txt;) || Echo=%%J)>"%%H" Del "%%~nH.tmp~" 2>NUL))

為了清楚起見,我對您的要求的閱讀是,將.\data中所有.mload文件中的所有行替換為不區分大小寫的字符串.LOGON ,替換為.RUN FILE logon.txt 行;

感謝菲爾的建議,但沒有奏效。

奇怪的是,我嘗試使用行尾字符$而不是行首 ^ ,它似乎已經成功了。

似乎^被視為文字,甚至 escaping 它與\都無法按預期工作。

第一個工作解決方案

FOR /F "delims=" %%i IN ('DIR *.ext1 /B') DO (
  SET "FILE=%%i"
  SETLOCAL EnableDelayedExpansion
  <!FILE! >!FILE!.tmp~ (
    REM Find line number on which Logon command is found
    FOR /F "tokens=1,* delims=:" %%j IN ('FINDSTR /I /N /R "^\.LOGON.*" !FILE!') DO (
      SET "NUM=%%j"
    )
    REM Print all lines along with line number at beginning
    FOR /F "tokens=1,* delims=" %%k IN ('FINDSTR /N "$" !FILE!') DO (
      SET "LINE=%%k"
      REM Replace entire content of Logon line with Run file command
      FOR /F "tokens=1,* delims=:" %%l IN ("!LINE!") DO IF %%l EQU !NUM! (
        echo(.RUN FILE logon.txt;
      ) ELSE (
        echo(!LINE:*:=!
      )
    )
  )
  MOVE /Y !FILE!.tmp~ !FILE!
  echo Auto-generated !FILE!
  ENDLOCAL
)

修訂的工作解決方案(感謝aschipfl

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0data" && (
    rem // Loop through all files with .mload file extension:
    for /F "delims=" %%I in ('dir /B /A:-D-H-S "*.mload"') do (
        < "%%I" > "%%I.tmp~" (
            rem // Use beginning of line position with .logon in the search string:
            for /F "tokens=1,* delims=:" %%J in ('findstr /I /N /R "^\.logon" "%%I"') do (
                rem // Use beginning of line position in the search string:
                for /F "delims=" %%K in ('type "%%I" ^| findstr /N "^"') do (
                    rem // Match current line number with previously searched line:
                    for /F "tokens=1,* delims=:" %%L in ("%%K") do if %%L equ %%J (
                        echo(.RUN FILE logon.txt;
                    ) else (
                        echo(%%M
                    )
                )
            )
        )
        > nul move /Y "%%I.tmp~" "%%I"
    )
    popd
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM