批处理脚本 - 修剪功能和删除空行

时间:2015-04-09 08:41:44

标签: batch-file automation

修剪功能:

批处理脚本中是否有修剪功能?即删除尾随和开始空间。需要将修剪功能应用于文本文件中的所有行。 下面是我到目前为止的脚本。但是这会删除任何第一个字符,希望它只删除空格(如果有的话)。

For /F "tokens=*" %%A in (Temp.txt) do (
    set line=%%A
    echo(!line:~1!>>Temp.txt
)

例如: 输入=

[Space][Space]This is just a example message[Space][Space]
[Space]This is second example message[Space][Space]
This is third example message[Space]

输出=

This is just a example message
This is second example message
This is third example message

[Space]等于1个空格字符。

删除空行:

如果行中只有空格/制表符而没有其他内容,如何删除它们? 示例: 下面是一行包含两个空格,然后是如何从文本文件中删除整行。

[SPACE][SPACE]

3 个答案:

答案 0 :(得分:1)

@echo off
setlocal

(for /F "tokens=*" %%a in (input.txt) do (
   if "%%a" neq "" (
      set "line=%%a"
      setlocal EnableDelayedExpansion
      call :rTrim
      echo !line!
      endlocal
   )
)) > output.txt
move /Y output.txt input.txt
goto :EOF

:rTrim
if "!line:~-1!" neq " " exit /B
set "line=!line:~0,-1!"
goto rTrim

以前的批处理文件基于以下操作细节:

  • FOR /F命令不处理空行,即删除空行。
  • "TOKENS=*"选项删除前导空格。
  • 如果未给出DELIMS=选项且一行只包含空格和/或标签,则%%a为空。

所以唯一复杂的部分是正确的修剪......

答案 1 :(得分:1)

以下是优化的纯批处理解决方案,无论必须修剪多少个字符,它都会与行数线性地执行。此解决方案也是对称的,因为它从每行的开头和结尾修剪空格和制表符,并完全删除任何结果为空的行。该脚本期望修剪文件作为参数传递。例如xtrim test.txtcall xtrim "c:\test\test.txt"。结果将覆盖原始文件。

<强> XTRIM.BAT

@echo off
setlocal disableDelayedExpansion
>"%~1.new" (
  for /f "usebackq eol= tokens=*" %%A in ("%~1") do if "%%A" neq "" (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    for %%k in (
      4096 2048 1024 512 256 128 64 32 16 8 4 2 1
    ) do for /f "eol= tokens=*" %%B in ("!ln:~-%%k!.") do (
      setlocal disableDelayedExpansion
      if "%%B" equ "." (
        endlocal
        set "ln=!ln:~0,-%%k!"
      ) else endlocal
    )
    echo !ln!
    endlocal
  )
)
move /y "%~1.new" "%~1" >nul

与任何纯批处理脚本一样,上面的代码不能处理大于〜8191字节的行,如果处理大文件,它会变得非常慢。但是,这个解决方案的速度和纯批次一样快。

我使用JREPL.BAT提供了一个更简单,更快速的解决方案 - 一个在文本文件上执行正则表达式查找/替换的实用程序。 JREPL.BAT是一个混合JScript /批处理脚本,可以在XP以后的任何Windows机器上本机运行。

以下一个内核具有完全相同的功能,除了它实际上没有限制(理论上每行最大约2千兆字节),并且在处理任何可观大小的文件时速度要快得多。

<强> JXTRIM.BAT

@jrepl "^[ \t]*(.*?)[ \t]*$" "$1?$1:false" /jmatch /f %1 /o -



我相信上述两种解决方案都符合OP的要求。但是,他们并没有完全按照要求做。我修剪了两个标签和空格,但OP只要求修剪前导和尾随空格。当删除整行时,OP仅要求删除标签,因为它是空的,或者因为它包含制表符和/或空格。

以下修改完全符合OP所规定的规范:

<强> XTRIM2.BAT

    @echo off
    setlocal disableDelayedExpansion
    >"%~1.new" (
      for /f "usebackq tokens=* eol= delims= " %%A in ("%~1") do if "%%A" neq "" (
        set "ln=%%A"
        setlocal enableDelayedExpansion
        for %%k in (
          4096 2048 1024 512 256 128 64 32 16 8 4 2 1
        ) do for /f "tokens=* delims= " %%B in ("!ln:~-%%k!.") do (
          setlocal disableDelayedExpansion
          if "%%B" equ "." (
            endlocal
            set "ln=!ln:~0,-%%k!"
          ) else endlocal
        )
        for /f "eol= " %%B in ("!ln!") do echo !ln!
        endlocal
      )
    )
    move /y "%~1.new" "%~1" >nul

<强> JXTRIM2.BAT

@jrepl "^[ ]*(.*[^ \t](.*[^ ])?)[ ]*$" "$1?$1:false" /jmatch /f %1 /o -

答案 2 :(得分:0)

Sub TrimSpace
    If LCase(Arg(1)) = "l" then 
        Do Until Inp.AtEndOfStream
            Line=Inp.readline
            outp.writeline LTrim(Line)
        Loop
    ElseIf LCase(Arg(1)) = "r" then
        Do Until Inp.AtEndOfStream
            Line=Inp.readline
            outp.writeline RTrim(Line)
        Loop
    ElseIf LCase(Arg(1)) = "lr" then
        Do Until Inp.AtEndOfStream
            Line=Inp.readline
            outp.writeline Trim(Line)
        Loop
    ElseIf LCase(Arg(1)) = "lc" then
        Count = Cint(LCase(Arg(2)))
'       msgbox count
        Do Until Inp.AtEndOfStream
            Line=Inp.readline
'           msgbox Line & "  " & Len(Left(Line,Count)) & "  " & Len(Mid(Line, Count)) & "  " & Len(Space(Count)) & "  " & Len(Line)  
'           msgbox Left(Line,Count) & "End" & vbcrlf & Space(Count) & "End"
            If Left(Line,Count) = Space(Count) then
                outp.writeline Mid(Line, Count +1)
            Else
                outp.writeline LTrim(Line)
            End If
        Loop
    End If
End Sub

Sub BlankLine
    Set RegEx = New RegExp
    RegEx.Pattern = "^\s+$"
        If LCase(Arg(1)) = "e" then
            Do Until Inp.AtEndOfStream
                Line=Inp.ReadLine
                If Len(Line) <> 0 Then
                    OutP.WriteLine Line
                End If
            Loop
        ElseIf Lcase(Arg(1)) = "a" then
            Do Until Inp.AtEndOfStream
                Line=Inp.ReadLine
                If Len(Line) <> 0 Then
                    If RegEx.Test(Line) = False then
                        OutP.WriteLine Line
                    End If
                End If
            Loop
        End If
End Sub

两个脚本都需要以下4行。

Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout

你需要调用sub。

使用修剪

cscript //nologo "path to script.vbs" "" l < "c:\inputfile" > "C:\outputfile"

和blanklines

cscript //nologo "path to script.vbs" "" a < "c:\inputfile" > "C:\outputfile"

https://skydrive.live.com/redir?resid=E2F0CE17A268A4FA!121是您可以将filter0.8.zip下载为易于使用的文件的地方。 Filter有19个文本文件函数和许多选项,是vbs处理文本文件的示例代码。显示它是多么容易。所有单独的功能都在一个子目录中。