批處理(bat)學習的一些總結
這篇筆記是我對批處理學習的一些總結,能在系統幫助里找到的內容我就不寫了,太偏門的也不寫,只寫些個人感覺很好用的技巧,大部分屬于整理
一、set 篇:
1、set(無開關)
set .=test
set.
::若一個變量以:\.這三個與路徑相關的符號開頭,用set查看以該字符打頭的變量時可以省去一個空格。
echo %tmp:*\=%
::顯示tmp變量第一個\之后的部分,其余變量替換與變量偏移太簡單不解釋
2、set /p 變量名=注釋<設備名
當設備名為文件時,因為文件中換行符與回車符伴生,所以只取文件第一行作為var變量的內容,但是不超過1024字節;而當設備名為nul或者com3時,只顯示不換行的注釋,這種情況下可以省略變量名(如:set /p=Hello World
3、set /a,最具技巧的命令之一
set /a n=1,m=2
::同時把不同數值分別賦予兩個變量
set /a a=b=c=d=e=f=1
::用一條算式為多個變量同時賦值
set /a "1/n" 2>nul||echo 變量n非純數字或為零
::利用分母不能為0的特征,用set判斷一個變量是否為非零純數字
set n=1
set /a "n=!!123|!!234&!!0"
::位運算,!、^、|和&常用于布爾運算,而邏輯位移常用于二進制運算(>>還可判斷數值是否為負,見下例)
set /a n=-100,"1/(-100>>31)"||echo 變量n為負數
::順應cmd中的正負數存儲特點,可以用邏輯位移實現判斷正負數的“布爾運算”,可以衍生出繁多的算法,比如稍加改動就可以比較兩數甚至多個數的大小
set /a n=~-100
::利用~將所有二進制的1、0逆轉,負號在后或在前配合可以實現簡單加1或減1,這個技巧主要用來減少括號的使用,因為~號與負號的優先級都是高于算數運算符的
set /a test=%test:~5,1%-0
::可以避免%test:~5,1%為空時出錯的情況
set /a 十進制=0x十六進制,十進制=0八進制
::快速將十六進制與八進制數轉為十進制,可惜沒有二進制...
:loop
set /a n+=1001
echo %n:~-3%
goto loop
::這比常規的補位方法更優越
for %%a in (test 123 ABC test @#$ 123) do set /a ".%%a+=1"
set .|findstr /v /e "=1"
::經典的獲取字符串的重復次數的方案
二、for 篇:
這是批處理中最強的內部命令,沒有之一!
1、for(無開關)
for %%a in (c:\*.*) do echo %%a
::顯示C盤根目錄下所有非隱藏、非系統屬性文件
for %%a in (.\..) do echo %%~nxa
::顯示上一級目錄的文件夾名
set str=123,234,345
set str=%str:,=\%
for %%a in (%str%\..) do echo %%~nxa
::用前一個技巧,巧取倒數第二段字符串,與for /f "delims=\"相映成趣
for %%a in (*.txt) do (
for /f "useback delims=" %%b in ("%%a") do (
set str=%%b
for %%c in ("!str:分隔符=" "!") do (
for /f "tokens=1*" %%d in (%%c) do echo %%~d
)
)
)
::不帶參數的for與for /f配合,威力極大,僅舉此一例
for %%a in (123) do for %%a in (234) do for %%a in (345) do echo %%a
::其實如果只讀取最后一層for的參數,即使多層for嵌套也可以使用同樣的參數,比如%%a
for %%z in (!tmp!) do echo !%%z!
::目前已知的擺脫call實現多層變量嵌套的最好方法,不少人用
2、for /l
for /l %%a in () do echo
::無限循環,步數為0也是一樣的效果,但是沒這個簡潔
for /l %%a in (-4 1) do echo %%a
::for /l中的三項參數從左至右的三位分別是初始值、步數、終止點,當用戶給定的數量不足時,將按從右至左的順序把不足的一項賦為0
3、for /d /r
for /r /d %%a in (*) do echo %%a
::可以遍歷所有子文件夾,之所以可以聯用r開關和d開關是因為它們的參數有交集,l開關和f開關就不行了。
4、for /f
for /f本身的技巧并不是特別多,它的優勢是能夠將其他命令的輸出作為輸入來分析,所以for /f可以說是當之無愧的內部命令之王
for /f "tokens=* delims=0123" %%a in ("0000123456") do echo %%a
::去除前綴的n個字符
for /f "skip=99" %%a in (1.txt) do echo 1.txt至少100行
::以前看到某版主寫的,印象頗深。
for /l %%a in (1 1 10) do (
for /f "tokens=1,2* delims=\" %%a in ("!tmp!") do (
for %%c in (%%a %%b) do echo %%c
set tmp=%%c
)
)
::將tokens的取值范圍無限拓展
set tmp=123=234=345=456
for /l %%a in (1 1 40) do (
for /f "tokens=1,2* delims==" %%a in ("!tmp!") do (
set str=!str!,%%a,%%b
set tmp=%%c
)
)
echo %str:~1%
::有時候set變量替換是無法替換一些特殊字符的,此時可以用for /f處理
set test=d:\test\
for %%a in (test.*) do (
if "%%~za" neq "%%~z$test:a" replace /p /u "%%a" "%%~dp$test:a"
)
::判斷當前目錄下以test為名的文件是否在d:\test\文件夾下存在同名文件,如果存在且大小不同、修改日期更早,則替換之,否則不做處理。for幫助信息中的“%%~dp$path:a”參數似乎沒見人用過,雖然它的適用范圍很狹隘,但是特定的情況下不妨一試。
setlocal enabledelayedexpansion
set t=tmp
set @=t
for /f %%a in ('echo !%@%!') do echo !%%a!
::另一種三層嵌套方法,其實不實用。
三、findstr 篇
我最鐘愛的命令,可惜外部命令的啟動速度太慢,所以實際運用時較少露面。
findstr /s /m .* *.*
::其實findstr也是一個dir,雖然比dir慢些,卻多了查找文件內容的功能
findstr /n .* 1.txt|findstr "^5000:"
::非常實用的取指定行的方法,配合正則可以取指定范圍之內的行
set /p n=請輸入數字或大小寫字母
(echo !n!)|findstr /i "[0-9a-Z]"&&echo 輸入有誤!
::這個夠實用吧?不解釋
dir|findstr ['-Z]
::利用findstr和if命令中字符的實際大小順序實現查找含有寬字符的行
findstr /x ".........." 1.txt
::查找1.txt中10字節的行
(type 1.txt&echo;)|findstr /o .*|more +1
::加上for,很容易獲取1.txt每行的字節數
findstr>1.txt /m /p .* *.*
dir /b /a-d|findstr>2.txt /v /i /m /g:1.txt
::獲取含有不可打印字符的文件名,關鍵是findstr取集
findstr "^Rar!" /g:1.txt
::此處1.txt是上個技巧的1.txt,內容是所有含不可打印字符的文件列表,此技巧可搜索rar文件,雖然簡單,但是至今也未出錯過,原創。
more>tmp +2 1.txt
findstr>前兩行.txt /x /v /g:1.txt 2.txt
::有時候可用此辦法獲取前幾行,當然,絕大部分情況下沒有for /f合適,而且存在特殊字符bug
@echo off
findstr /n .* 1.txt>tmp1
find /n /v "" 2.txt|more>tmp2 +2
for /f "tokens=2*delims=]:" %%a in ('fc /n /lb10000 tmp1 tmp2^|sort') do (
echo;%%b
)
del tmp?
pause
::qzwqzw首創用fc /n同時輸出雙文本的思路,但是存在排序有可能被打亂的缺陷,所以加了個find彌補一下