【问题标题】:Batch Script - Trim functionality and Removing blank lines批处理脚本 - 修剪功能和删除空行
【发布时间】:2015-04-11 00:17:15
【问题描述】:

修剪功能:

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

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

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

删除空行:

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

[SPACE][SPACE]

【问题讨论】:

    标签: batch-file automation


    【解决方案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 GB),并且在处理任何可感知大小的文件时速度要快得多。

    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】:
    @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 为空。

    所以唯一复杂的部分是正确的装饰......

    【讨论】:

    • 相当不错,除了它只右修剪空格,但它左修剪空格和制表符。此外,如果需要进行大量的右修剪,它会变得非常慢
    • 另外,如果第一个非空格、非制表符是分号,则会错误地删除非空行。您需要将 EOL 设置为空格。我的第一次尝试有同样的错误:-)
    • 修剪函数中的Exit /B 是否结束整个脚本本身?看起来好像它只是结束递归修剪并返回到 for 循环。
    • @Lastwish: :rTrim 是通过call 命令调用的,所以在其中执行的exit /B 只是结束它并返回到调用rTrim 的地方。顺便说一句,rTrim 不是递归的:里面没有任何call 命令...
    【解决方案3】:
    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"
    

    和空白行

    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 处理文本文件的示例代码。显示它是多么容易。所有单独的功能都在一个子中。

    【讨论】:

      猜你喜欢
      • 2016-12-20
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2011-06-15
      相关资源
      最近更新 更多