【问题标题】:Removing non alphanumeric characters in a batch variable删除批处理变量中的非字母数字字符
【发布时间】:2013-11-20 06:40:25
【问题描述】:

如何批量删除变量中的所有非字母数字(a-z、A-Z、0-9、_)字符?

我很确定我需要使用 findstr 和正则表达式。

【问题讨论】:

  • 我想,findstr 和正则表达式在这里没有帮助,因为它可以找到一些东西,但它不能替代任何东西
  • 那么你以后就可以更换它了。

标签: batch-file cmd alphanumeric non-alphanumeric


【解决方案1】:

MC ND 的解决方案有效,但速度很慢(小测试样本需要 ~1 秒)。

这是由 echo "!_buf!"|findstr ... 构造引起的,因为管道会为每个字符创建两个 cmd.exe 实例并启动 findstr。

但这也可以通过纯批处理来解决。
测试每个字符是否在map 变量中

:test

    set "_input=Th""i\s&& is not good _maybe_???"
    set "_output="
    set "map=abcdefghijklmnopqrstuvwxyz 1234567890"

:loop
if not defined _input goto endLoop    
for /F "delims=*~ eol=*" %%C in ("!_input:~0,1!") do (
    if "!map:%%C=!" NEQ "!map!" set "_output=!_output!%%C"
)
set "_input=!_input:~1!"
    goto loop

:endLoop
    echo(!_output!

当goto 循环被移除时,它可能会加速。
然后,您需要先计算 stringLength,然后在每个字符上使用 FOR/L 循环进行迭代。
该解决方案比上述方法快约 6 倍,比 MC ND 的解决方案快约 40 倍

set "_input=Th""i\s&& is not good _maybe_!~*???"
set "_output="
set "map=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890"
%$strLen% len _input

for /L %%n in (0 1 %len%) DO (
    for /F "delims=*~ eol=*" %%C in ("!_input:~%%n,1!") do (
        if "!map:%%C=!" NEQ "!map!" set "_output=!_output!%%C"
    )
)
exit /b

宏 $strlen 可以定义为

set LF=^


::Above 2 blank lines are required - do not remove
@set ^"\n=^^^%LF%%LF%^%LF%%LF%^^":::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
        for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
            set "str=A!%%~2!"%\n%
              set "len=0"%\n%
              for /l %%A in (12,-1,0) do (%\n%
                set /a "len|=1<<%%A"%\n%
                for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
              )%\n%
              for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
        ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,

【讨论】:

    【解决方案2】:

    已编辑 - @jeb 是对的。这有效,但非常非常慢。

    @echo off
        setlocal enableextensions enabledelayedexpansion
        set "_input=Th""i\s&& is not good _maybe_???"
        set "_output="
    :loop
        if not defined _input goto endLoop
        set "_buf=!_input:~0,1!"
        set "_input=!_input:~1!"
        echo "!_buf!"|findstr /i /r /c:"[a-z 0-9_]" > nul && set "_output=!_output!!_buf!"
        goto loop
    :endLoop
        echo !_output!
        endlocal
    

    所以,回到绘图板。如何让它更快?让我们尝试尽可能少地执行操作,并尽可能多地使用长子字符串。所以,分两步完成

    1.- 删除所有可能产生问题的坏字符。为此,我们将使用 for 命令的能力将这些字符识别为分隔符,然后将字符串的其余部分连接起来

    2.- 删除其余的坏字符,使用有效字符作为分隔符将它们定位在字符串中以查找坏字符的子字符串,然后替换字符串中

    所以,我们以 (sintax 适应这里已经回答的内容) 结束

    @echo off
    
        setlocal enableextensions enabledelayedexpansion
    
        rem Test empty string
        call :doClean "" output
        echo "%output%"
    
        rem Test mixed strings
        call :doClean "~~asd123#()%%%^"^!^"~~~^"""":^!!!!=asd^>^<bm_1" output
        echo %output%
        call :doClean "Thi\s&& is ;;;;not ^^good _maybe_!~*???" output
        echo %output%
    
        rem Test clean string
        call :doClean "This is already clean" output
        echo %output%
    
        rem Test all bad string
        call :doClean "*******//////\\\\\\\()()()()" output
        echo "%output%"
    
        rem Test long string
        set "zz=Thi\s&& is not ^^good _maybe_!~*??? "
        set "zz=TEST: %zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%"
        call :doClean "%zz% TEST" output
        echo %output%
    
        rem Time long string
        echo %time%
        for /l %%# in (1 1 100) do call :doClean "%zz%" output
        echo %time%
    
        exit /b
    
    rem ---------------------------------------------------------------------------
    :doClean input output
        setlocal enableextensions enabledelayedexpansion
        set "map=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 "
        set "input=%~1"
        set "output="
    
    rem Step 1 - Remove critical delimiters
    (
    :purgeCritical
        for /L %%z in (1 1 10) do (
            for /f tokens^=1^-9^,^*^ delims^=^=^"^"^~^;^,^&^*^%%^:^!^(^)^<^>^^ %%a in ("!input!") do ( 
                set "output=!output!%%a%%b%%c%%d%%e%%f%%g%%h%%i"
                set "input=%%j" 
            )
            if not defined input goto outPurgeCritical
        )
        goto purgeCritical
    )
    :outPurgeCritical
    
    rem Step 2 - remove any remaining special character
    (
    :purgeNormal
        for /L %%z in (1 1 10) do (
            set "pending="
            for /f "tokens=1,* delims=%map%" %%a in ("!output!") do (
                set "output=!output:%%a=!"
                set "pending=%%b"
            )
            if not defined pending goto outPurgeNormal
        )
        goto purgeNormal
    )
    :outPurgeNormal
    
        endlocal & set "%~2=%output%"
        goto :EOF
    

    也许不是最快的,但至少是一个“体面”的解决方案

    【讨论】:

      【解决方案3】:
      @echo eof
      
      call :purge "~~asd123#()%%%^"^!^"~~~^:^=asd^>^<bm_1" var
      echo (%var%)
      goto :eof
      
      
      :purge StrVar  [RtnVar]
      setlocal disableDelayedExpansion
      set "str1=%~1"
      setlocal enableDelayedExpansion
      
      for %%a in ( -  ! @ # $ % ^^ ^&  + \ / ^< ^>  . '  [ ] { }  ` ^| ^"  ) do (
         set "str1=!str1:%%a=!"
       )
      
       rem dealing with some delimiters
      
      
       set "str1=!str1:(=!"
       set "str1=!str1:)=!"
       set "str1=!str1:;=!"
       set "str1=!str1:,=!"
       set "str1=!str1:^^=!"
       set "str1=!str1:^~=!"
      
       set "temp_str=" 
       for %%e in (%str1%) do (
        set "temp_str=!temp_str!%%e"
       )
      
      endlocal & set "str1=%temp_str%"
      
      
      
      setlocal disableDelayedExpansion
      set "str1=%str1:!=%"
      set "str1=%str1::=%"
      set "str1=%str1:^^~=%"
      
      for /f "tokens=* delims=~" %%w in ("%str1%") do set "str1=%%w"
      
      endlocal & set "str1=%str1%"
      
      
      
      endlocal &  if "%~2" neq "" (set %~2=%str1%) else echo %str1%
      
      goto :eof
      

      仍然无法处理~ and =,但正在努力

      编辑: = 现在将被清除 编辑: ~ 现在将被清除

      【讨论】:

      • 但是 ! 的替代在 FOR 循环中不起作用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 2018-05-05
      • 2013-11-29
      • 1970-01-01
      相关资源
      最近更新 更多