如何使用Windows命令提示符修剪文本文件中的所有尾随空格?
Ben Hocking提到的DosTips RTRIM函数可以用来创建一个可以正确修剪文本文件中每一行的脚本。 但是,功能相对较慢。
DosTips用户(和主持人)aGerman开发了一个非常有效的右调整算法 。 他将算法实现为批量“宏” – 这是一个将复杂的小脚本存储在可以从内存执行的环境变量中的有趣概念。 有争论的宏是本身的一个重要的讨论话题,与这个问题无关。
我已经提取了一个德国人的算法,并把它放在下面的批处理脚本。 该脚本需要文本文件的名称作为唯一的参数,然后右键修剪文件中每行的空格。
@echo off setlocal enableDelayedExpansion set "spcs= " for /l %%n in (1 1 12) do set "spcs=!spcs!!spcs!" findstr /n "^" "%~1" >"%~1.tmp" setlocal disableDelayedExpansion ( for /f "usebackq delims=" %%L in ("%~1.tmp") do ( set "ln=%%L" setlocal enableDelayedExpansion set "ln=!ln:*:=!" set /a "n=4096" for /l %%i in (1 1 13) do ( if defined ln for %%n in (!n!) do ( if "!ln:~-%%n!"=="!spcs:~-%%n!" set "ln=!ln:~0,-%%n!" set /a "n/=2" ) ) echo(!ln! endlocal ) ) >"%~1" del "%~1.tmp" 2>nul
假设脚本被称为rtrimFile.bat,那么可以从命令行调用它,如下所示:
rtrimFile "fileName.txt"
关于表演的说明
原始的DosTips rtrim功能执行线性搜索,默认最多可裁剪32个空格。 它必须在每个空间迭代一次。
aGerman的算法使用二分搜索,并且能够在13次迭代中修整批次允许的最大字符串大小(高达〜8k个空格)。
不幸的是,当处理文本时批处理非常慢。 即使使用高效的rtrim功能,在我的机器上修剪1MB文件也需要大约70秒的时间。 问题是,只是读写文件而不做任何修改需要花费大量的时间。 这个答案使用一个FOR循环来读取文件,加上FINDSTR在每行的前面加上行号,这样空行就被保留下来了。 它切换延迟扩展,以防止!
免受损坏,并使用搜索和替换操作从每行删除行号前缀。 所有这一切,甚至在开始做rtrim之前。
通过使用使用set /p
的备用文件读取机制,性能可能会提高近一倍。 但是,set / p方法限制为每行大约1k字节,并且从每一行中去除尾随控制字符。
如果你需要定期修剪大文件,那么即使性能提高一倍也可能是不够的。 有时间下载(如果可能的话)任何一个可以在瞬间处理文件的实用程序。
如果您不能使用非本机软件,那么您可以尝试通过CSCRIPT批处理命令执行的VBScript或JScript。 要么其中一个会更快。
更新 – 与JREPL.BAT快速解决方案
JREPL.BAT是一个正则表达式查找/替换工具,可以非常有效地解决问题。 这是纯粹的脚本(混合批处理/ JScript),可以从XP以后的任何Windows机器上本机运行。 没有第三方exe文件是必要的。
使用JREPL.BAT在PATH中的某处,可以使用以下简单命令从文件“test.txt”中去除尾随空格:
jrepl " +$" "" /f test.txt /o -
如果将该命令放在批处理脚本中,则必须在命令前加上CALL:
call jrepl " +$" "" /f test.txt /o -
去自己找一份CygWin或者GnuWin32 的sed
软件包 。
然后使用命令:
sed "s/ *$//" inputFile >outputFile
Dos Tips提供了一个RTrim实现,用于批处理文件:
:rTrim string char max -- strips white spaces (or other characters) from the end of a string :: -- string [in,out] - string variable to be trimmed :: -- char [in,opt] - character to be trimmed, default is space :: -- max [in,opt] - maximum number of characters to be trimmed from the end, default is 32 :$created 20060101 :$changed 20080219 :$categories StringManipulation :$source http://www.dostips.com SETLOCAL ENABLEDELAYEDEXPANSION call set string=%%%~1%% set char=%~2 set max=%~3 if "%char%"=="" set char= &rem one space if "%max%"=="" set max=32 for /l %%a in (1,1,%max%) do if "!string:~-1!"=="%char%" set string=!string:~0,-1! ( ENDLOCAL & REM RETURN VALUES IF "%~1" NEQ "" SET %~1=%string% ) EXIT /b
如果你不习惯在批处理文件中使用函数, 请阅读 。
删除Windows中文件尾部空格的好工具: http : //mountwhite.net/en/spaces.html
我刚刚找到一个非常好的解决方案,用于修剪字符串的空格:
你有没有使用call
子例程,并扩展所有参数使用%*
? 您会注意到任何前导和/或尾随的空格都被删除。 其他角色之间出现的任何空格都会被保留。 所有其他的命令令牌分隔符,, ;
, =
还有非中断空格(字符代码0xFF
)。 这个效果我将用于我的脚本:
@echo off set "STR=" set /P STR="Enter string: " rem /* Enable Delayed Expansion to avoid trouble with rem special characters: `&`, `<`, `>`, `|`, `^` */ setlocal EnableDelayedExpansion echo You entered: `!STR!` call :TRIM !STR! echo And trimmed: `!RES!` endlocal exit /B :TRIM set "RES=%*" exit /B
该脚本需要用户输入的字符串,然后进行修剪。 这当然也可以应用在文件的行上(原来的问题是关于这个问题的,但是使用for /F
来读取这样的行在其他答案中总是显示出来,所以我在这里略过)。 要仅修剪一侧的字符串,请在修剪之前将单个字符添加到另一侧,然后将其删除。
这种方法虽然有一些限制:它不处理字符%
!
, ^
和"
正确。为了克服这个问题,需要几个中间字符串操作操作:
@echo off setlocal EnableExtensions DisableDelayedExpansion set "STR=" set /P STR="Enter string: " setlocal EnableDelayedExpansion echo You entered: `!STR!` set "STR=!STR:%%=%%%%!" set "STR=!STR:"=""!^" if not "%STR%"=="%STR:!=%" set "STR=!STR:^=^^^^!" set "STR=%STR:!=^^^!%" call :TRIM !STR! set "RES=!RES:""="!^" echo And trimmed: `!RES!` endlocal endlocal exit /B :TRIM set "RES=%*" exit /B
更新:我刚刚意识到字符&
, <
, >
和|
仍然造成麻烦。 一旦我找到解决方案,我将回到这里,并相应地修复代码…
根据用户Aacini的 回答 ,删除尾部空格是个不错的技巧; 我修改了它,以便保留字符串中出现的所有其他空格。 所以这里是代码:
@echo off setlocal EnableDelayedExpansion rem // This is the input string: set "x= This is a text string containing many spaces. " rem // Ensure there is at least one trailing space; then initialise auxiliary variables: set "y=%x% " & set "wd=" & set "sp=" rem // Now here is the algorithm: set "y=%y: =" & (if defined wd (set "y=!y!!sp!!wd!" & set "sp= ") else (set "sp=!sp! ")) & set "wd=%" rem // Return messages: echo input: "%x%" echo output: "%y%" endlocal
但是,这种方法失败的时候,一个字符集^
!
, "
出现在字符串中。
我使用这个Python 2脚本来打印尾随空格的行并手动删除它们:
#!/usr/bin/env python2 import sys if not sys.argv[1:]: sys.exit('usage: whitespace.py <filename>') for no, line in enumerate(open(sys.argv[1], 'rb').read().splitlines()): if line.endswith(' '): print no+1, line
我知道Python并没有预装Windows,但至少它是跨平台的。