如何使用Windows命令提示符修剪文本文件中的所有尾随空格?
答案 0 :(得分:8)
Ben Hocking引用的DosTips RTRIM函数可用于创建可以修剪文本文件中每一行的脚本。但是,功能相对较慢。
DosTips用户(和主持人)aGerman开发了very efficient right trim algorithm。他将算法实现为批处理“宏” - 将复杂的迷你脚本存储在可以从内存执行的环境变量中的有趣概念。带有参数的宏本身就是一个主要的讨论主题,与这个问题无关。
我已经提取了一个德国算法并将其放入以下批处理脚本中。该脚本需要将文本文件的名称作为唯一参数,然后向右调整文件中每行的空格。
@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之前所有这一切。
使用alternate file read mechanism that uses 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 -
答案 1 :(得分:4)
答案 2 :(得分:2)
Dos Tips有一个适用于批处理文件的implementation of 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
如果您不习惯在批处理文件中使用函数read this。
答案 3 :(得分:1)
根据用户this answer的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
但是,当字符串中出现^
,!
,"
字符时,此方法会失败。
答案 4 :(得分:0)
用于删除Windows中文件的尾随空格的好工具: http://mountwhite.net/en/spaces.html
答案 5 :(得分:0)
我刚刚找到了一个非常好的解决方案来修剪字符串的空格:
您是否曾使用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
更新: 我刚才意识到字符&
,<
,>
和|
仍然会导致麻烦。一旦找到解决方案,我将回到这里并相应地修改代码......
答案 6 :(得分:-1)
我使用这个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预装,但至少它可以跨平台工作。