背景
前幾天幫助一個同事寫了一個批處理,分析一個文件,並做以下處理:
- 固定刪除第10行。
- 如果里面有“127.0.0.1”字樣,需要全部替換成“192.168.0.89”。
- 其他不涉及的需要原樣輸出。
- 文本可能包含各種字符,即可能包含批處理的特殊字符,如!、“”、>、|等。
完成上述條件的難度在於,替換字符串時,特殊字符會被丟掉。最后查了很多資料,不負所托,終於完成了任務。在此對本次實現涉及的知識點做一下筆記。
在開始文章之前,首先要感謝大家,因為我查了很多資料,可能到處都會抄一點來用,如果涉及您那一部分,萬望不要介意。
本次腳本主要涉及的知識點有兩個:
- 批處理內的函數調用。
- 批處理對文章的原樣輸出。
批處理內的函數調用
批處理的調用函數其實就是跳轉標簽,但是使用call來調用(而不是用goto),然后使用exit /b X(X代表數字,比如1、2、3、100等)返回,而X就是調用函數的返回值,使用errorlevel獲取。如下例子:
@echo off set “checkstr= check is have hello” call :checkreturn %checkstr% if %errorlevel%. equ 100. (echo yes, have hello! & goto :end) echo no, we don’t have hello! goto :end :checkreturn If %1. equ . (exit /b 0) if %1. equ hello. (exit /b 100) shift goto :checkreturn exit /b 0 :end pause exit
本例是通過“調用函數”checkreturn來檢測語句中是否存在“hello”這個單詞,如果存在,則返回100,並打印“yes, have hello!”,否則便返回0,並打印“no, we don’t have hello!”。
批處理原樣輸出文件
如果要原樣輸出文章(包括特殊字符)的目的,則需要注意在必要的地方開啟和關閉環境延遲變量。如下例子:
cd.>output.txt for /f "delims=" %%i in ('findstr /n .* 123.txt') do ( set "var=%%i" setlocal enabledelayedexpansion set var=!var:*:=! (echo.!var!)>>output.txt endlocal )
本例只是原樣輸出文章,不做任何修改和判斷,能支持文章內存在各種特殊字符。
結合實現
上面兩個例子都是非常簡單的,但這兩個知識點是本次實現的核心。結合上面兩個例子,我們可以達到了解決問題的目的,具體腳本如下:
@echo off set filepath="D:\123.txt" set skipline=10 set oldreplacestr=127.0.0.1 set newreplacestr=192.168.0.89 cd.>output.txt echo start translation... echo ---------------------------------------------------- echo. for /f "delims=" %%i in ('findstr /n .* %filepath%') do ( set "var=%%i" setlocal enabledelayedexpansion set line=!var:^>=! set line=!line::= ! call :checkline !line! if !errorlevel!. neq 1. ( set var=!var:%oldreplacestr%=%newreplacestr%! set var=!var:*:=! echo.!var! (echo.!var!)>>output.txt) endlocal ) echo. echo ---------------------------------------------------- echo translate complete. echo. goto :end :checkline if %1. equ . (exit /b 0) if %1. equ %skipline%. (exit /b 1) exit /b 0 :end pause exit
總結
在完成這個腳本過程中,我們得到一些結論:
- 應該在適當的地方開啟延遲環境變量。
- 任何替換操作都要在開啟延遲環境變量之后、關閉延遲環境變量之前處理。
- 如果需要調用函數,需要先把一些特殊字符替換掉,比如>。
- 只有不怕數據破壞(針對特殊字符)的條件下才調用函數,即調用函數判斷的,都是不完全依賴原數據的,只需要關鍵數據即可。比如上例,只需要判斷是否是第10行,而不管別的數據是否被破壞,而最后輸出到文本的數據,用的是原始數據(var),而不是判斷數據(line)。