如何删除批处理文件中用户提供的输入的尾随和前导空格?

问题描述 投票:0回答:17

我知道在预定义变量时如何执行此操作。但是,当要求用户输入某种输入时,如何修剪前导和尾随空格?这是我到目前为止所拥有的:

@echo off

set /p input=:
echo. The input is %input% before

::trim left whitespace
for /f "tokens=* delims= " %%a in ("%input%") do set input=%%a
::trim right whitespace (up to 100 spaces at the end)
for /l %%a in (1,1,100) do if "!input:~-1!"==" " set input=!input:~0,-1! 

echo. The input is %input% after

pause
input batch-file whitespace trim
17个回答
34
投票

下面的解决方案对我来说非常有效。

仅 4 行,适用于大多数(全部?)字符


解决方案:

:Trim
SetLocal EnableDelayedExpansion
set Params=%*
for /f "tokens=1*" %%a in ("!Params!") do EndLocal & set %1=%%b
exit /b

测试:

@echo off

call :Test1 & call :Test2 & call :Test3 & exit /b

:Trim
SetLocal EnableDelayedExpansion
set Params=%*
for /f "tokens=1*" %%a in ("!Params!") do EndLocal & set %1=%%b
exit /b

:Test1
set Value=   a b c   
set Expected=a b c
call :Trim Actual %Value%
if "%Expected%" == "%Actual%" (echo Test1 passed) else (echo Test1 failed)
exit /b

:Test2
SetLocal EnableDelayedExpansion
set Value=   a \ / : * ? " ' < > | ` ~ @ # $ [ ] & ( ) + - _ = z    
set Expected=a \ / : * ? " ' < > | ` ~ @ # $ [ ] & ( ) + - _ = z
call :Trim Actual !Value!
if !Expected! == !Actual! (echo Test2 passed) else (echo Test2 failed)
exit /b

:Test3
set /p Value="Enter string to trim: " %=%
echo Before: [%Value%]
call :Trim Value %Value%
echo After : [%Value%]
exit /b

29
投票

需要开启延迟扩容。试试这个:

@echo off
setlocal enabledelayedexpansion
:blah
set /p input=:
echo."%input%"
for /f "tokens=* delims= " %%a in ("%input%") do set input=%%a
for /l %%a in (1,1,100) do if "!input:~-1!"==" " set input=!input:~0,-1!
echo."%input%"
pause
goto blah

19
投票

我正在使用的一个非常简短且简单的解决方案是:

@ECHO OFF

SET /p NAME=- NAME ? 
ECHO "%NAME%"
CALL :TRIM %NAME% NAME
ECHO "%NAME%"
PAUSE

:TRIM
SET %2=%1
GOTO :EOF

结果:

- NAME ?  my_name
" my_name "
"my_name"

12
投票

我想提出一个紧凑的解决方案,使用对函数和“子函数”的引用调用(是的,“批处理”也有指针!):

  @ECHO OFF
  SETLOCAL ENABLEDELAYEDEXPANSION

  SET /p NAME=- NAME ? 
  ECHO "%NAME%"
  CALL :TRIM NAME
  ECHO "%NAME%"
  GOTO :EOF

  :TRIM
  SetLocal EnableDelayedExpansion
  Call :TRIMSUB %%%1%%
  EndLocal & set %1=%tempvar%
  GOTO :EOF

  :TRIMSUB
  set tempvar=%*
  GOTO :EOF

6
投票

为了改进 Forumpie 的答案,技巧是在子部分中使用

%*
(所有参数):

编辑:添加了 TRIM 子例程参数的回显,以提供更多见解

@ECHO OFF

SET /p NAME=- NAME ? 
ECHO "%NAME%"
CALL :TRIM %NAME%
SET NAME=%TRIMRESULT%
ECHO "%NAME%"

GOTO :EOF

:TRIM
  echo "%1"
  echo "%2"
  echo "%3"
  echo "%4"
  SET TRIMRESULT=%*
GOTO :EOF

这会去除前导空格和尾随空格,但保留之间的所有空格。

"  1 2    3 4    "
"1 2    3 4"

%*详情:批量参数


4
投票

这是我的快速而肮脏的解决方案。请注意,如果输入文本包含文件名中禁止的字符,将会产生意想不到的结果。

@echo off
set /p input=Enter some text with spaces before and after^>
echo "%input%"
for /f "tokens=*" %%i in ('echo %input%') do set trimmed=%%~nxi
echo "%trimmed%"

编辑

为了提供更强大的文本输入字符集,并仍然删除通常由 for in ('echo...') 方法留下的单个尾随空格,这是一种替代方法:

set /p input=Enter some text with spaces before and after^>
for /f "tokens=*" %%i in ('echo %input%') do set j=%%i
set trimmed=%j:~0,-1%
echo "%trimmed%"

2
投票

您还可以通过将带有空格的变量作为参数传递到子函数中来去除空格,然后在子函数中只需使用传入的参数再次设置它们即可。

@echo off 
set "a=    apple      "
set "b=     banana    "
echo [%a%]
echo [%b%]
call :Strip %a% %b%
pause
goto :EOF

:Strip
set a=%1
set b=%2
echo [%a%]
echo [%b%]

----------------
Results....
[    apple      ]
[     banana    ]
[apple]
[banana]
Press any key to continue . . .

1
投票

下面的

:trimAll
子程序:

  • 修剪传递给它的字符串中的前导和尾随制表符和空格
  • 可以在禁用或启用延迟扩展的情况下安全地调用
  • 处理有毒字符(例如,
    !
    %
    ^
    等)
  • 不支持 CR 和 LF

阅读评论以获取参考和信息。

@echo off & setLocal enableExtensions disableDelayedExpansion
:: https://www.dostips.com/forum/viewtopic.php?t=4308
(call;) %= sets errorLevel to 0 =%
(set lf=^
%= BLANK LINE REQUIRED =%
)
:: kudos to Carlos for superior method of capturing CR
:: https://www.dostips.com/forum/viewtopic.php?p=40757#p40757
set "cr=" & if not defined cr for /f "skip=1" %%C in (
    'echo(^|replace ? . /w /u'
) do set "cr=%%C"

set ^"orig=  !random!  !  ^^!  ^^^^!  ^"^^  ^&^"^&  ^^^" %%os%%  ^"

call :trimAll res1 orig
setLocal enableDelayedExpansion
call :trimAll res2 orig
echo(orig: [!orig!]
echo(res1: [!res1!]
echo(res2: [!res2!]
endLocal

endLocal & goto :EOF

:trimAll result= original=
:: trims leading and trailing whitespace from a string
:: special thanks to Jeb for
:: https://stackoverflow.com/a/8257951
setLocal
set "ddx=!" %= is delayed expansion enabled or disabled? =%
setLocal enableDelayedExpansion
set "die=" & if not defined %2 (
    >&2 echo(  ERROR: var "%2" not defined & set "die=1"
) else set "str=!%2!" %= if =%

if not defined die for %%L in ("!lf!") ^
do if "!str!" neq "!str:%%~L=!" (
    >&2 echo(  ERROR: var "%2" contains linefeeds & set "die=1"
) %= if =%

if not defined die for %%C in ("!cr!") ^
do if "!str!" neq "!str:%%~C=!" (
    >&2 echo(  ERROR: var "%2" contains carriage returns
    set "die=1"
) %= if =%

if defined die goto die

(for /f eol^= %%A in ("!str!") do rem nop
) || (
    >&2 echo(WARNING: var "%2" consists entirely of whitespace
    endLocal & endLocal & set "%1=" & exit /b 0
) %= cond exec =%

:: prepare string for trimming...
:: double carets
set "str=!str:^=^^^^!"
:: double quotes
set "str=!str:"=""!"
:: escape exclaims
set "str=%str:!=^^^!%" !

:: act of CALLing subfunction with
:: expanded string trims trailing whitespace
call :_trimAll "%%str%%

:: prepare string to be passed over endLocal boundary...
:: double carets again if delayed expansion enabled
if not defined ddx set "str=!str:^=^^^^!"
:: escape exclaims again if delayed expansion enabled
if not defined ddx set "str=%str:!=^^^!%" !
:: restore quotes
set "str=!str:""="!"

:: pass string over endLocal boundary and trim leading whitespace
for /f tokens^=*^ eol^= %%a in ("!str!") do (
    endLocal & endLocal & set "%1=%%a" !
) %= for /f =%
exit /b 0

:die
endLocal & endLocal & set "%1=" & exit /b 1

:_trimAll
:: subfunction
:: trailing exclaim is required as explained by Jeb at
:: https://www.dostips.com/forum/viewtopic.php?p=6933#p6933
set "str=%~1" !
exit /b 0

HTH 和 HNY! ;)


1
投票

刚刚想出这个:

set sString=" hello|123(4) "
call :trimMENew %sString%
echo "%sString%"
exit /b 0

:trimMeNew
set "sString=%~1"
if "%sString:~0,1%" == " " set "sString=%sString:~1%"
if "%sString:~-1%" == " " set "sString=%sString:~0,-1%"
exit /b 0

1
投票

我发现这里介绍的所有解决方案对我来说都不够完整,并且在某种情况下不起作用。

注意

似乎 stackoverflow 错误地处理了复制粘贴代码中的制表字符(并丢失了其他字符,如

\x01
\x04
),因此如果直接通过 CTRL+C 复制,下面的代码可能不起作用。使用文末链接直接下载脚本。

trim_var.bat

@echo off

rem USAGE:
rem   trim_var.bat <Var> [<OutVar>]

rem drop the output variable value
if not "%~2" == "" if not "%~1" == "%~2" set "%~2="

if not defined %~1 exit /b 0

setlocal DISABLEDELAYEDEXPANSION

setlocal ENABLEDELAYEDEXPANSION & for /F "eol= tokens=* delims=" %%i in ("!%~1!") do endlocal & set "RETURN_VALUE=%%i"

:TRIM_LEFT_LOOP
if not defined RETURN_VALUE exit /b 0
if not ^%RETURN_VALUE:~0,1%/ == ^ / if not ^%RETURN_VALUE:~0,1%/ == ^   / goto TRIM_RIGHT_LOOP
set "RETURN_VALUE=%RETURN_VALUE:~1%"
if not defined RETURN_VALUE exit /b 0
goto TRIM_LEFT_LOOP

:TRIM_RIGHT_LOOP
if not defined RETURN_VALUE exit /b 0
if not ^%RETURN_VALUE:~-1%/ == ^ / if not ^%RETURN_VALUE:~-1%/ == ^ / goto TRIM_RIGHT_LOOP_END
set "RETURN_VALUE=%RETURN_VALUE:~0,-1%"
goto TRIM_RIGHT_LOOP

setlocal ENABLEDELAYEDEXPANSION & for /F "eol= tokens=* delims=" %%i in ("!RETURN_VALUE!") do endlocal & endlocal & if not "%~2" == "" ( set "%~2=%%i" ) else set "%~1=%%i"
exit /b 0

echo_var.bat:

@echo off

rem USAGE:
rem   echo_var.bat <Var> [<Prefix> [<Suffix>]]

setlocal DISABLEDELAYEDEXPANSION

set "__?VAR__=%~1"
if not defined __?PREFIX__ set "__?PREFIX__=%~2"
if not defined __?SUFFIX__ set "__?SUFFIX__=%~3"

if not defined __?VAR__ exit /b 255
if not defined %__?VAR__% exit /b 1

rem safe echo
setlocal ENABLEDELAYEDEXPANSION & for /F "eol= tokens=* delims=" %%i in ("!__?PREFIX__!!%__?VAR__%!!__?SUFFIX__!") do endlocal & echo.%%i
exit /b 0

test_trim_var.bat

@echo off

setlocal DISABLEDELAYEDEXPANSION

set myvar1=              1 ! 2 ^| 3 ^& 4 ^^ 5 = 6 , 7 ; 8 * 9 # 0 %% 1 / 2 \ 3 ? 4 ^> 5 ^< 6 " 7             

call "trim_var.bat" myvar1 myvar2

call "echo_var.bat" myvar1 - -
call "echo_var.bat" myvar2 - -

输出

-                        1 ! 2 | 3 & 4 ^ 5 = 6 , 7 ; 8 * 9 # 0 % 1 / 2 \ 3 ? 4 > 5 < 6 " 7               -
-1 ! 2 | 3 & 4 ^ 5 = 6 , 7 ; 8 * 9 # 0 % 1 / 2 \ 3 ? 4 > 5 < 6 " 7-

最新实现:https://github.com/andry81/contools/tree/HEAD/Scripts/Tools/std/trim_var.bat

优点

  • 安全处理几乎所有特定字符,如
    !
    %
    ^
    "

缺点

  • \x04
    代码字符用作EOL字符。

0
投票
  @echo off & setlocal enableextensions
  rem enabledelayedexpansion
  set S=  This  is  a  test
  echo %S%.
  for /f "tokens=* delims= " %%a in ('echo %S%') do set S=%%a
  echo %S%.
  endlocal & goto :EOF

来自 http://www.netikka.net/tsneti/info/tscmd079.htm

用于删除前导空格。


0
投票

我是这样做的(暂时开启延迟扩展):

      ...
sqlcmd -b -S %COMPUTERNAME% -E -d %DBNAME% -Q "SELECT label from document WHERE label = '%DOCID%';" -h-1 -o Result.txt
      if errorlevel 1 goto INVALID
    :: Read SQL result and trim trailing whitespace
    SET /P ITEM=<Result.txt
    @echo ITEM is %ITEM%.
    setlocal enabledelayedexpansion
    for /l %%a in (1,1,100) do if "!ITEM:~-1!"==" " set ITEM=!ITEM:~0,-1!
    setlocal disabledelayedexpansion
    @echo Var ITEM=%ITEM% now has trailing spaces trimmed.
....

0
投票
@echo off
setlocal EnableDelayedExpansion
set S=  This  is  a  test
echo %S%.
for /f "tokens=* delims= " %%a in ('echo %S%') do (set b=%%a & set b=!b: =! & echo !b!)
endlocal & goto :EOF

@echo off
setlocal EnableDelayedExpansion
set S=  This  is  a  test
echo %S%.
for /f "tokens=* delims= " %%a in ('echo %S%') do (set b=%%a & set b=!b: =_! & echo !b!)
endlocal & goto :EOF

0
投票
for /f "usebackq tokens=*" %%a in (`echo %StringWithLeadingSpaces%`) do set StringWithout=%%a

这很简单。

for
不带任何参数则认为空格为分隔符;将“*”设置为
tokens
参数会导致程序收集字符串中非空格的所有部分,并将它们放入一个新字符串中,并在其中插入自己的间隙。


0
投票

我必须创建一个函数。

将其用作:

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION


set "TextString=    Purple Cows are flying in the Air Tonight         "
echo REM ^^Notice there is whitespace at the start and end of the TextString
echo "!TextString!"
CALL:trimWhiteSpace "!TextString!" OutPutString
echo Resulting Trimmed Text: "!OutPutString!"
echo REM ^^Now there should be no White space at the start or end.

Exit /B

将其添加到批处理文件的底部:

:FUNCTIONS
@REM FUNCTIONS AREA
GOTO:EOF
EXIT /B


::TRIM FUNCTIONS AREA::
:: USAGE:
:: trimWhiteSpace "!InputText!" OutputText
:: Remember to use the "! on the input text, but NOT on the Output text.
:: The Following is Wrong: trimWhiteSpace "!InputText!" !OutputText!
:: ^^Because it has a ! around the OutPutText
:: Make Sure to add " around the InputText when running the call.
:: If you don't add the " then it will only accept the first word before a space.
::Example:
::  set "TextString=    Purple Cows are flying in the Air Tonight         "
::  echo REM ^^Notice there is whitespace at the start and end of the TextString
::  echo "!TextString!"
::  CALL:trimWhiteSpace "!TextString!" OutPutString
::  echo Resulting Trimmed Text: "!OutPutString!"
::  echo REM ^^Now there should be no White space at the start or end.

:trimWhiteSpace
set textToTrim=%~1
CALL:trimWhiteSpaceOnTheRight "!textToTrim!" OutPutString
SET textToTrim=!OutPutString!
CALL:trimWhiteSpaceOnTheLeft "!textToTrim!" OutPutString
SET %2=!OutPutString!
GOTO:EOF

:trimWhiteSpaceOnTheRight
set str=%~1
for /l %%a in (1,1,31) do if "!str:~-1!"==" " set str=!str:~0,-1!
SET %2=%str%
GOTO:EOF

:trimWhiteSpaceOnTheLeft
set str=%~1
for /f "tokens=* delims= " %%a in ("%str%") do set str=%%a
SET %2=%str%
GOTO:EOF

请记住,您必须将“SETLOCAL ENABLEDELAYEDEXPANSION”添加到批处理文件的顶部,否则这些都无法正常工作。

SETLOCAL ENABLEDELAYEDEXPANSION
@REM # Remember to add this to the top of your batch file.

-2
投票

设置 newVarNoSpaces=%someVarWithSpaces: =%


-5
投票

Thank you @Bradley Mountford

我正在使用“修剪右侧空白”,完全适用于我的“Show-Grp-of-UID.CMD”。 :) 欢迎其他改进意见..^_^

© www.soinside.com 2019 - 2024. All rights reserved.