使用Windows批处理从文件中删除尾随空格?

时间:2012-02-16 11:45:13

标签: windows batch-file cmd

如何使用Windows命令提示符修剪文本文件中的所有尾随空格?

7 个答案:

答案 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)

CygWin获取the sed packageGnuWin32的副本。

然后使用命令:

sed "s/ *$//" inputFile >outputFile

答案 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 answerAacini删除尾随空格有一个很好的技巧;我修改了它,以便保留字符串中出现的所有其他空格。所以这是代码:

@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预装,但至少它可以跨平台工作。