【问题标题】:In batch split a string to new lines in file by delimiter通过分隔符将字符串批量拆分为文件中的新行
【发布时间】:2020-09-30 16:08:58
【问题描述】:

在批处理中,我尝试将字符串拆分为子字符串,最好基于分隔符。

这个例子有效,但有没有更好的方法来做到这一点:

for /f "tokens=1-20 delims=:" %%a in (string.txt) do (
echo %%a& echo.%%b& echo.%%c& echo.%%d& echo.%%e& echo.%%f& echo.%%g& echo.%%h& echo.%%i& echo.%%j
echo.%%k& echo.%%l& echo.%%m& echo.%%n& echo.%%o& echo.%%p& echo.%%q& echo.%%r& echo.%%s& echo.%%t
) >substrings.txt

我尝试过 Magoo 的 this code,它适用于默认分隔符,但使用冒号失败:

@echo off
setLocal 
for /f "delims=:" %%a in (string.txt) do (
for %%i in (%%a) do echo %%i >>substrings.txt
)

我也尝试过来自 Aacini 的 this code,但使用特殊字符似乎失败了。

@echo off
setlocal EnableDelayedExpansion

set i=1
set "x=%string%"
set "x!i!=%x::=" & set /A i+=1 & set "x!i!=%"
set x >substrings.txt

%string% var 或 string.txt 的示例是:

Select project:/option:report name="Sustainability":option value="201":Huonville:/option:/report:report name="Energy and Water Management":option value="102":Cygnet:/option:/report:report name="Tree Management":option value="101":Cygnet:/option:/report:option disabled="disabled":/option:/select

我正在尝试将 %string% var 或 string.txt 输出到 substring.txt,如下所示:

Select project
/option
report name="Sustainability"
option value="201"
Huonville
/option
/report
report name="Energy and Water Management"
option value="102"
Cygnet
/option
/report
report name="Tree Management"
option value="101"
Cygnet
/option
/report
option disabled="disabled"
/option
/select

任何帮助将不胜感激。谢谢

【问题讨论】:

    标签: batch-file split substring


    【解决方案1】:

    查看@dbenham 的惊人CERTUTIL 字符串替换technique。它适用于任何字符,甚至 exclams!

    @echo off
    ====SETLOCAL EnableDelayedExpansion EnableExtensions
    
    
    set "B=^!"
    set "C=^"
    set ^"L=^
    %===Line Feed===%
    "
    for /F "eol=N" %%C in ('wmic os get Name /value') do set "R=%%C" Carriage Return
    set ^"E=!R!!L!" CRLF
    
    
    >nul 2>&1 certutil -f -encodehex String.txt "%temp%\hex.txt" 4
    
    
    pushd "%temp%"
    >expand.txt (FOR /F "delims=" %%A in (hex.txt) do FOR %%B in (%%A) do (
        set "char=%%B"
        REM ! --> !B! ###
        set "char=!char:21=21 42 21!"
        REM ^ --> !C! ###
        set "char=!char:5e=21 43 21!"
        REM <CR> --> !R! ###
        set "char=!char:0a=21 4c 21!"
        REM <LF> --> !L! ###
        set "char=!char:0d=21 52 21!"
    
    
        REM : --> !R!!L! ###
        set "char=!char:3a=21 45 21!"
        echo(!char!
    ))
    
    
    >nul 2>&1 certutil -f -decodehex expand.txt rawContent.txt
    for /f delims^=^ eol^= %%A in (rawContent.txt) do set "modified=%%A"
    del hex.txt expand.txt rawContent.txt
    popd
    
    
    >substring.txt (
    echo(!modified!
    )
    

    【讨论】:

      【解决方案2】:

      这是对 Stephan 的想法的总结。

      @echo off
      setlocal enabledelayedexpansion
      set /p string=<"input.txt"
      set "string=%string: =@%"
      set "string="%string::=" "%"
      (for %%a in (%string%) do (
        set "output=%%~a"  
        echo !output:@= !
      ))>output.txt
      

      设置字符串或输入文本文件(修改第 3 行)。

      set /p string=&lt;"input.txt"

      本例中的分隔符是冒号 [:] 跟在 [string:] 之后(修改第 5 行)。

      set "string="%string::=" "%"

      如果 stringinput.txt 包含引号 %string% em> 可能需要双引号(修改第 3 行)。

      for /f "delims=" %%a in (input.txt) do (set string="%%a")

      @echo off
      setlocal enabledelayedexpansion
      for /f "delims=" %%a in (input.txt) do (set string="%%a")
      set "string=%string: =@%"
      set "string="%string::=" "%"
      (for %%a in (%string%) do (
        set "output=%%~a"  
        echo !output:@= !
      ))>output.txt
      

      【讨论】:

        【解决方案3】:

        当您使用for /f 时,您需要知道有多少令牌(并且有最大令牌限制)。

        您需要一个普通的for 循环,但您无法选择应该使用哪个分隔符。

        所以用空格替换每个分隔符。确保在每个“令牌”周围加上引号以处理原始空间。为此,请在整个字符串周围加上引号并将分隔符 : 替换为 " "

        @echo off
        setlocal enabledelayedexpansion
        set "string=Select project:/option:report name="Sustainability":option value="201":Huonville:/option:/report:report name="Energy and Water Management":option value="102":Cygnet:/option:/report:report name="Tree Management":option value="101":Cygnet:/option:/report:option disabled="disabled":/option:/select""
        
        set "string=%string: =@%"
        set "string="%string::=" "%"
        (for %%a in (%string%) do (
          set "out=%%~a"  
          echo !out:@= !
        ))>out.txt
        echo take a look at the modified string:
        echo %string%
        echo/
        type out.txt
        

        另一种方法(仅出于学术原因):

         @echo off
        setlocal 
        set "string=Select project:/option:report name="Sustainability":option value="201":Huonville:/option:/report:report name="Energy and Water Management":option value="102":Cygnet:/option:/report:report name="Tree Management":option value="101":Cygnet:/option:/report:option disabled="disabled":/option:/select"
        
        call :recur %string%
        goto :eof
        
        :recur
        rem echo loop with %*
        for /f "tokens=1,* delims=:" %%a in ("%*") do ( 
          echo %%a
          if not "%%~b" == "" call :recur %%b
          goto :eof
        )
        echo.
        

        注意:存在递归限制(由于堆栈大小)。它适用于给定的字符串,但当字符串包含更多“令牌”时可能会失败。

        【讨论】:

        • 我不确定我是否在关注。我可以使用空格而不是冒号 : 输出 string.txt 作为分隔符,但这会破坏原始空格,这就是为什么我认为使用冒号 : 会更好。但是据我了解,Stephan 您的代码需要冒号: 分隔符将所有标记包装在周围的引号" " 中,并且修改后的字符串将作为普通的for 循环再次运行。它是否正确?也许我应该坚持echo. lol
        • 是的,你总结得很好。查看第一个代码的最后一行以查看要由for 解析的更改后的字符串。 Foralpha beta 作为两个“令牌”,但将 "alpha beta" 作为一个(这是用于保持原始空间不变的技巧)。
        • Stephan 能否请您演示一下我如何将更改后的字符串 echo 转换为新行,因为我仍然得到一个长(更改后的)字符串。将字符串分解为子字符串的目的是让我可以使用for /f %%a in ('findstr "search" "substring.txt"') 进行搜索
        • “变长的字符串”只是为了给你看。见之前的输出。我用find 更改了我的第一个代码。
        • 输出在空格处被破坏。它在“长更改字符串”中看起来是正确的,但如果我尝试使用搜索或重定向来自 ...echo %%~a) &gt;substrings.txt 的输出,则标记已损坏。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-16
        • 2014-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多