DOS/BAT

关注公众号 jb51net

关闭
首页 > 脚本专栏 > DOS/BAT > bat 删除空行空格

bat实现删除文本中的空行、空格、制表符、最后一行空行

作者:小青龍

本文主要介绍了 bat实现删除文本中的空行、空格、制表符、最后一行空行

这篇文章将演示 bat批处理如何删除文件中空白行、空格、制表符

一、准备测试数据

准备一个old_file.txt文件,UTF-8编码,内容如下:

first line
second line    
    third line    

	forth line		
	    
	fifth line    
		
    sixth line	  
    	
	测试  1  	
        
    测试	2   
Finish      

Notepad++中,显示所有字符,截图看下

old_file.txt

二、通过for /f实现

1. 删除仅含换行符的空行

Windows系统下CR LF表示换行符

@echo off
for /F "delims=" %%l in (old_file.txt) do (
	echo.%%l>>new_file1.txt
)

Tips:

执行结果:
新旧文本对比(肉眼对比),可以看出第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:

经过上边两次替换,如果仍不为空,则表示该行为非空白行,然后 echo.%%L输出原行内容

执行结果:
新旧文本对比,可以看出仅含换行符、仅含空格或指标符的空白行(第4、6、8、10、12行)去除了。

删除所有空白行

3. 删除所有空白行以及非空白行左侧的空格和制表符

@echo off
for /F "tokens=*" %%L in (old_file.txt) do (
	if not "%%L"=="" echo.%%L
)>>new_file3.txt

Tips:

执行结果:
新旧文本对比,可以看出所有空白行及非空白行左侧的空格或制表符都去掉了

删除空白行及左侧空白

4. 删除所有空白行以及非空白行两侧的空格和制表符

@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:

执行结果:
新旧文本对比,可以看出所有空白行、非空白行两侧的空格和制表符都去掉了,中间的空格和制表符仍保留

删除空白行及非空白行两侧的空格和制表符

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:

执行结果:
新旧文本对比,可以看出所有空白行、所有空格和制表符(包括文字中间的)都去掉了

删除文中所有空白行及所有空格和制表符

三、通过findstr实现

1. 删除仅含换行符的空行

@echo off
findstr /v /r /c:"^$" old_file.txt > new_file6.txt
::或者
::findstr . old_file.txt > new_file6.txt

Tips:

一般表达式快速参考:

表达式解释说明
.通配符: 任何字符
*重复: 以前字符或类出现零或零以上次数
^行位置: 行的开始
$行位置: 行的终点
[class]字符类: 任何在字符集中的字符
[^class]补字符类: 任何不在字符集中的字符
[x-y]范围: 在指定范围内的任何字符
\xEscape: 元字符 x 的文字用法
\<xyz字位置: 字的开始
xyz\>字位置: 字的结束

执行结果:
新旧文本对比,可以看出第4行仅含换行符的空白行被去除了

findstr删除空行

2. 删除所有空白行

删除仅含换行符、仅含空格或制表符的空白行

@echo off
findstr /v /r /c:"^[ 	]*$" old_file.txt >new_file7.txt

Tips:

执行结果:
新旧文本对比,可以看出仅含换行符、仅含空格或指标符的空白行(第4、6、8、10、12行)去除了。

删除所有空白行

无法通过 findstr 的方式,实现删除非空白行两侧的空格和制表符

四、删除文件最后一行空行

我这里有个需求将old_file.txt文件中仅含换行符的空行及最后一行去掉,文件内容如下
(这里只给截图,准备数据里有,只是最后一行有区别)

在这里插入图片描述

然后你再使用【二、通过for /f实现】中的批处理脚本处理修改后的old_file.txt文件,你会发现新生成的文件Finish....后边始终会多出来一个CR LF换行符,其实这是因为 echo在输出内容时会自动在行尾尾随一个CR LF,大多数情况下这也没啥影响,但假如(无论原文件中是否有最后一行空行)你就想在新生成的文件中去掉它,该如何处理呢?

尝试了几种方法,总结如下:

1. 使用set /p=实现

代码来源: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 

执行结果:
新旧文本对比,你会发现,最后一行不再有CR LF,但是每行的开头的空格或制表符也一并给去掉了。但我这个脚本最初的意图删除仅含换行符的空行以及最后一行空行。

这是因为set /p =会使 前导引号空格剥离,前导=报错语法错误,在不同的Windows版本之间限制会有不同,有关详细讨论参见:
SET /P prompt mechanics - New behavior: = makes syntax error

删除效果

2. 使用backspace回退字符实现

为了解决set /p=导致的,前导空格或制表符剥离的问题,有大神提出了,使用backspace回退字符的方案

@echo off
chcp 65001 & cls
setlocal EnableExtensions DisableDelayedExpansion 
::获取回退字符并存储到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窗口的输出效果

对比结果

对比原文本可以看出,对于tab制表符作为前导的行,backspace并未生效,其余的生效了。

然后代码做下改动,输出到new_file.txt文件,看下效果。

@echo off
setlocal EnableExtensions DisableDelayedExpansion 
::获取回退字符并存储到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 

看下输出结果对比,可以发现backspace回退字符,在重定向到文件后,完全无效,+未被回退,还多出来一个BS字符

输出结果对比

我也尝试了

<nul set /p "_s=.◘%%L"

参考:
是一个backspace字符,在不同的CodePage下可能显示不同,测试效果同上,也仅在dos窗口上有效,重定向到文件后无效,这里不再演示了

3. 使用echo+set /p=实现

@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:

执行结果:
可以发现,已经能满足我的使用场景:删除仅含换行符的空行以及最后一行空行

结果对比

4. 使用prompt+cmd /d /k <nul实现

然后我又在 Output text without linefeed, even with leading space or = 评论区里看到了jeb大神给出的set "prompt=[promptString]"+cmd /d /k < nul的方案。
不过这里的promptString最长为511字符,你也可以到这里看相关说明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
	)
)

执行结果:
可以发现,已经能满足我的使用场景:删除仅含换行符的空行以及最后一行空行

执行结果对比

五、总结

参考资料:

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?

到此这篇关于 bat实现删除文本中的空行、空格、制表符、最后一行空行的文章就介绍到这了,更多相关 bat 删除空行空格内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文