bat實(shí)現(xiàn)刪除文本中的空行、空格、制表符、最后一行空行
這篇文章將演示 bat批處理如何刪除文件中空白行、空格、制表符
一、準(zhǔn)備測(cè)試數(shù)據(jù)
準(zhǔn)備一個(gè)old_file.txt
文件,UTF-8編碼,內(nèi)容如下:
first line second line third line forth line fifth line sixth line 測(cè)試 1 測(cè)試 2 Finish
在Notepad++
中,顯示所有字符,截圖看下
二、通過for /f實(shí)現(xiàn)
1. 刪除僅含換行符的空行
Windows系統(tǒng)下CR
LF
表示換行符
@echo off for /F "delims=" %%l in (old_file.txt) do ( echo.%%l>>new_file1.txt )
Tips:
echo.%%l>>
,.
不能省略,%%l
與>>
之間不能有空格,不然空格會(huì)在新結(jié)果中出現(xiàn);echo.
你可以替換成echo+
、echo;
、echo:
等等,關(guān)于echo這種用法的更多討論可參考:ECHO. FAILS to give text or blank line - Instead use ECHO/
執(zhí)行結(jié)果:
新舊文本對(duì)比(肉眼對(duì)比),可以看出第4行僅含換行符的空白行被去除了。
注意:最后一行不含任何字符的保持原樣
2. 刪除所有空白行
刪除僅含換行符、僅含空格或制表符的空白行
@echo off setlocal enabledelayedexpansion for /F "delims=" %%L in (old_file.txt) do ( set "str=%%L" set "str1=!str: = !" set "str2=!str1: =!" if not "!str2!"=="" echo.%%L )>>new_file2.txt endlocal
Tips:
set "str1=!str: = !"
,注意這里的被替換字符是一個(gè)制表符
,將制表符
替換為空格
(嘗試了將制表符
替換為空,會(huì)出現(xiàn)第8行兩個(gè)指標(biāo)符的行仍原樣輸出了。。。不知道為啥);set "str2=!str1: =!"
,將空格
替換為空;
經(jīng)過上邊兩次替換,如果仍不為空,則表示該行為非空白行,然后 echo.%%L
輸出原行內(nèi)容
執(zhí)行結(jié)果:
新舊文本對(duì)比,可以看出僅含換行符、僅含空格或指標(biāo)符的空白行(第4、6、8、10、12行)去除了。
3. 刪除所有空白行以及非空白行左側(cè)的空格和制表符
@echo off for /F "tokens=*" %%L in (old_file.txt) do ( if not "%%L"=="" echo.%%L )>>new_file3.txt
Tips:
if not "%%L"=="" echo.%%L
如果換成echo.%%L
,則僅含空格或制表符的行,將輸出為僅含換行符的空行。
執(zhí)行結(jié)果:
新舊文本對(duì)比,可以看出所有空白行及非空白行左側(cè)的空格或制表符都去掉了
4. 刪除所有空白行以及非空白行兩側(cè)的空格和制表符
@echo off setlocal enabledelayedexpansion for /F "tokens=*" %%L in (old_file.txt) do ( set "str=%%L" call :rdel if not "!str!"=="" echo !str!>>new_file4.txt ) endlocal goto :eof :rdel set tmp=%str% :sloop if "%tmp%"=="" goto eloop if "%tmp:~-1%"==" " ( set "tmp=%tmp:~0,-1%" goto sloop ) if "%tmp:~-1%"==" " ( set "tmp=%tmp:~0,-1%" goto sloop ) :eloop set "str=%tmp%" goto :eof
Tips:
- 定義了一個(gè)
rdel
函數(shù),用來去除非空白行右側(cè)的空格和制表符(為什么未寫去除左側(cè)的空格和制表符,因?yàn)?code>for /F "tokens=*"已經(jīng)把左側(cè)的去除了)
執(zhí)行結(jié)果:
新舊文本對(duì)比,可以看出所有空白行、非空白行兩側(cè)的空格和制表符都去掉了,中間的空格和制表符仍保留
5. 刪除所有空白行以及所有空格和制表符
@echo off setlocal enabledelayedexpansion for /F "delims=" %%L in (old_file.txt) do ( set "str=%%L" set "str1=!str: = !" set "str2=!str1: =!" if not "!str2!"=="" echo.!str2! )>>new_file5.txt endlocal
Tips:
- 其實(shí)就是將【2. 刪除所有空白行】的代碼中
echo.%%L
換成了echo.!str2!
執(zhí)行結(jié)果:
新舊文本對(duì)比,可以看出所有空白行、所有空格和制表符(包括文字中間的)都去掉了
三、通過findstr實(shí)現(xiàn)
1. 刪除僅含換行符的空行
@echo off findstr /v /r /c:"^$" old_file.txt > new_file6.txt ::或者 ::findstr . old_file.txt > new_file6.txt
Tips:
/v
僅打印不包含匹配項(xiàng)的行;/r
將搜索字符串作為一般表達(dá)式使用;
一般表達(dá)式快速參考:
表達(dá)式 | 解釋說明 |
---|---|
. | 通配符: 任何字符 |
* | 重復(fù): 以前字符或類出現(xiàn)零或零以上次數(shù) |
^ | 行位置: 行的開始 |
$ | 行位置: 行的終點(diǎn) |
[class] | 字符類: 任何在字符集中的字符 |
[^class] | 補(bǔ)字符類: 任何不在字符集中的字符 |
[x-y] | 范圍: 在指定范圍內(nèi)的任何字符 |
\x | Escape: 元字符 x 的文字用法 |
\<xyz | 字位置: 字的開始 |
xyz\> | 字位置: 字的結(jié)束 |
/c:string
使用指定字符串作為文字搜索字符串findstr .
表示包含任何字符的行,因此除第4行,其余都滿足
執(zhí)行結(jié)果:
新舊文本對(duì)比,可以看出第4行僅含換行符的空白行被去除了
2. 刪除所有空白行
刪除僅含換行符、僅含空格或制表符的空白行
@echo off findstr /v /r /c:"^[ ]*$" old_file.txt >new_file7.txt
Tips:
"^[ ]*$"
的[]
內(nèi)是<space>
<tab>
兩個(gè)字符,這個(gè)表達(dá)式的意思是:從行首到行尾,僅有0個(gè)或多個(gè)空格或制表符;
執(zhí)行結(jié)果:
新舊文本對(duì)比,可以看出僅含換行符、僅含空格或指標(biāo)符的空白行(第4、6、8、10、12行)去除了。
無法通過 findstr 的方式,實(shí)現(xiàn)刪除非空白行兩側(cè)的空格和制表符
四、刪除文件最后一行空行
我這里有個(gè)需求將old_file.txt
文件中僅含換行符的空行及最后一行去掉,文件內(nèi)容如下
(這里只給截圖,準(zhǔn)備數(shù)據(jù)里有,只是最后一行有區(qū)別)
然后你再使用【二、通過for /f
實(shí)現(xiàn)】中的批處理腳本處理修改后的old_file.txt
文件,你會(huì)發(fā)現(xiàn)新生成的文件Finish....
后邊始終會(huì)多出來一個(gè)CR LF
換行符,其實(shí)這是因?yàn)?nbsp;echo
在輸出內(nèi)容時(shí)會(huì)自動(dòng)在行尾尾隨一個(gè)CR LF
,大多數(shù)情況下這也沒啥影響,但假如(無論原文件中是否有最后一行空行)你就想在新生成的文件中去掉它,該如何處理呢?
嘗試了幾種方法,總結(jié)如下:
1. 使用set /p=實(shí)現(xiàn)
代碼來源:batfile - how to remove the last, empty, line in a file?
@echo off setlocal EnableExtensions DisableDelayedExpansion set "FLAG=" > "new_file.txt" ( for /F "usebackq delims=" %%L in ("old_file.txt") do ( if defined FLAG echo. ::echo.|set /P "dummyName=%%L" < nul set /P "dummyName=%%L" set "FLAG=#" ) ) endlocal exit /B
執(zhí)行結(jié)果:
新舊文本對(duì)比,你會(huì)發(fā)現(xiàn),最后一行不再有CR LF
,但是每行的開頭的空格或制表符也一并給去掉了。但我這個(gè)腳本最初的意圖刪除僅含換行符的空行以及最后一行空行。
這是因?yàn)?code>set /p =會(huì)使 前導(dǎo)引號(hào)
或空格
剝離,前導(dǎo)=
報(bào)錯(cuò)語法錯(cuò)誤,在不同的Windows版本之間限制會(huì)有不同,有關(guān)詳細(xì)討論參見:
SET /P prompt mechanics - New behavior: = makes syntax error
2. 使用backspace回退字符實(shí)現(xiàn)
為了解決set /p=
導(dǎo)致的,前導(dǎo)空格或制表符剝離的問題,有大神提出了,使用backspace
回退字符的方案
@echo off chcp 65001 & cls setlocal EnableExtensions DisableDelayedExpansion ::獲取回退字符并存儲(chǔ)到bs變量 for /F %%a in ('"prompt $H & for %%b in (1) do rem"') do (set "bs=%%a") ::處理文本 set "FLAG=" ( for /F "usebackq delims=" %%L in ("old_file.txt") do ( if defined FLAG echo. < nul set /P "dummyName=+%bs%%%L" set "FLAG=#" ) ) endlocal pause >nul
上邊代碼僅輸出到dos窗口,先來看下在dos窗口的輸出效果
對(duì)比原文本可以看出,對(duì)于tab
制表符作為前導(dǎo)的行,backspace
并未生效,其余的生效了。
然后代碼做下改動(dòng),輸出到new_file.txt
文件,看下效果。
@echo off setlocal EnableExtensions DisableDelayedExpansion ::獲取回退字符并存儲(chǔ)到bs變量 for /F %%a in ('"prompt $H & for %%b in (1) do rem"') do (set "bs=%%a") ::處理文本 set "FLAG=" > "new_file.txt" ( for /F "usebackq delims=" %%L in ("old_file.txt") do ( if defined FLAG echo. < nul set /P "dummyName=.%bs%%%L" set "FLAG=#" ) ) endlocal exit /B
看下輸出結(jié)果對(duì)比,可以發(fā)現(xiàn)backspace
回退字符,在重定向到文件后,完全無效,+
未被回退,還多出來一個(gè)BS
字符
我也嘗試了
<nul set /p "_s=.?%%L"
參考:?
是一個(gè)backspace
字符,在不同的CodePage
下可能顯示不同,測(cè)試效果同上,也僅在dos窗口上有效,重定向到文件后無效,這里不再演示了
3. 使用echo+set /p=實(shí)現(xiàn)
@echo off for /F "delims=" %%L in (old_file.txt) do ( setlocal enabledelayedexpansion if defined row echo.!row! endlocal set row=%%L )>>new_file1.txt echo.|set /p "=%row%" >>new_file1.txt
Tips:
for /f
部分使用echo
輸出除最后一行外的內(nèi)容,echo.|set /p
部分負(fù)責(zé)輸出最后一行,set /p
抑制了最后一行尾隨的換行符,所以最后不會(huì)出現(xiàn)一個(gè)空行。
執(zhí)行結(jié)果:
可以發(fā)現(xiàn),已經(jīng)能滿足我的使用場(chǎng)景:刪除僅含換行符的空行以及最后一行空行
4. 使用prompt+cmd /d /k <nul實(shí)現(xiàn)
然后我又在 Output text without linefeed, even with leading space or = 評(píng)論區(qū)里看到了jeb
大神給出的set "prompt=[promptString]"
+cmd /d /k < nul
的方案。
不過這里的promptString
最長(zhǎng)為511字符,你也可以到這里看相關(guān)說明How do I add a space on this line?
@echo off set flag= > new_file.txt ( for /F "delims=" %%L in (old_file.txt) do ( setlocal if defined flag echo. set "prompt=%%L" cmd /d /k < nul endlocal set flag=T ) )
執(zhí)行結(jié)果:
可以發(fā)現(xiàn),已經(jīng)能滿足我的使用場(chǎng)景:刪除僅含換行符的空行以及最后一行空行
五、總結(jié)
- 【四、刪除文件最后一行空行】中 1、2 都不滿足我的需求;3、4 可以滿足我的需求;當(dāng)然使用batch實(shí)現(xiàn)刪除文件最后一行空行的方式肯定還有,文末列出的參考資料里也有很多其他方案可供參考,也建議仔細(xì)閱讀,相信你會(huì)有不少收獲。
findstr
實(shí)現(xiàn)的【1. 刪除僅含換行符的空行】【2. 刪除所有空白行】從效率和安全性上都比for /f
實(shí)現(xiàn)的要好很多。
參考資料:
Windows Batch: How remove all blank (or empty) lines
Batch: remove all white spaces from a text file?
batfile - how to remove the last, empty, line in a file?
Windows batch: echo without new line
Output text without linefeed, even with leading space or =
How do I add a space on this line?
到此這篇關(guān)于 bat實(shí)現(xiàn)刪除文本中的空行、空格、制表符、最后一行空行的文章就介紹到這了,更多相關(guān) bat 刪除空行空格內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
統(tǒng)計(jì)每個(gè)數(shù)的重復(fù)次數(shù),并按照重復(fù)次數(shù)由高到低排序的批處理
統(tǒng)計(jì)每個(gè)數(shù)的重復(fù)次數(shù),并按照重復(fù)次數(shù)由高到低排序2009-05-05命令行下一種新的添加帳號(hào)的方法(Shell.Users)
用戶控制面板文件nusrmgr.cpl,發(fā)現(xiàn)調(diào)用的是Shell.Users來加用戶,它還同時(shí)調(diào)用了 wscript.shell、Shell.Application、Shell.LocalMachine這三個(gè)組件。2010-09-09純腳本備份_還原驅(qū)動(dòng)增強(qiáng)版附相關(guān)sleep.exe
不能說此腳本比驅(qū)動(dòng)精靈更完美,但它確實(shí)彌補(bǔ)了驅(qū)動(dòng)精靈的不足! 這個(gè)版本是我先前版本上(借助DevCon純腳本備份驅(qū)動(dòng))增強(qiáng)的,已經(jīng)是完美版本了。2008-06-06