Как удалить конечные и начальные пробелы для пользовательского ввода в командном файле?
Я знаю, как это сделать, когда переменная предопределена. Тем не менее, при запросе ввода пользователем какого-либо ввода, как мне обрезать начальные и конечные пробелы? Это то, что я до сих пор:
@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
17 ответов
Вам необходимо включить отложенное расширение. Попробуй это:
@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
Решение ниже работает очень хорошо для меня.
Всего 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%]
Очень короткое и простое решение, которым я пользуюсь:
@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"
Я хотел бы представить компактное решение, использующее вызов по ссылке (да, у "пакета" тоже есть указатели!) На функцию и "подфункцию":
@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
Чтобы улучшить ответ 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"
Сведения о%*: параметры партии
Это было мое быстрое и грязное решение. Обратите внимание, что это приведет к неожиданным результатам, если входной текст содержит символы, запрещенные в именах файлов.
@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%"
Вы также можете удалить пробелы, передав эти переменные с пробелами в качестве параметров в подпрограмму, а затем внутри своей подпрограммы просто установите их снова с переданными параметрами.
@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 . . .
: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://stackru.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!;)
Просто придумал это:
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
Я обнаружил, что все представленные здесь решения для меня недостаточно полны и не работают в том или ином случае.
ВНИМАНИЕ:
Кажется, что stackru неправильно обрабатывает символы табуляции (и теряет другие символы, такие как \x01
) в скопированном коде, поэтому приведенный ниже код может не работать, если вы скопируете его напрямую с помощью CTRL+C. Используйте ссылку в конце, чтобы напрямую загрузить скрипты.
trim_var.bat:
@echo off
rem drop the output variable value
if not "%~2" == "" if not "%~1" == "%~2" set "%~2="
if not defined %~1 exit /b 0
setlocal DISABLEDELAYEDEXPANSION
rem Load and replace a value quote characters by the \x01 character.
call set "RETURN_VALUE=%%%~1:"=%%"
: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
:TRIM_RIGHT_LOOP_END
rem recode quote and exclamation characters
set "__ESC__=^"
set __QUOT__=^"
set "__EXCL__=!"
set "RETURN_VALUE=%RETURN_VALUE:!=!__EXCL__!%"
set "RETURN_VALUE=%RETURN_VALUE:^=!__ESC__!%"
set "RETURN_VALUE=%RETURN_VALUE:=!__QUOT__!%"
rem safe set
setlocal ENABLEDELAYEDEXPANSION
for /F "tokens=* delims=" %%i in ("!RETURN_VALUE!") do for /F "tokens=* delims=" %%j in ("%%i") do (
endlocal
endlocal
if not "%~2" == "" (
set "%~2=%%j"
) else (
set "%~1=%%j"
)
)
exit /b 0
echo_var.bat:
@echo off
if not defined %~1 (
echo.%~2%~3
exit /b 0
)
setlocal DISABLEDELAYEDEXPANSION
rem Load and replace a value quote characters by the \x01 character.
call set "RETURN_VALUE=%%%~1:"=%%"
rem recode quote and exclamation characters
set "__ESC__=^"
set __QUOT__=^"
set "__EXCL__=!"
set "RETURN_VALUE=%RETURN_VALUE:!=!__EXCL__!%"
set "RETURN_VALUE=%RETURN_VALUE:^=!__ESC__!%"
set "RETURN_VALUE=%RETURN_VALUE:=!__QUOT__!%"
rem safe echo
setlocal ENABLEDELAYEDEXPANSION
for /F "tokens=* delims=" %%i in ("!RETURN_VALUE!") do for /F "tokens=* delims=" %%j in ("%%i") do (
endlocal
endlocal
echo.%~2%%j%~3
)
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://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools/std/trim_var.bat
Плюсы:
- Безопасно обрабатывает почти все определенные символы, такие как
!
,%
,^
,"
.
Минусы:
- В
"
символ заменяется на\x01
символ и может зависеть от текущей кодовой страницы (не проверено).
@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
Я сделал это так (временно включив отложенное расширение):
...
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.
....
@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
для удаления ведущих пробелов.
for /f "usebackq tokens=*" %%a in (`echo %StringWithLeadingSpaces%`) do set StringWithout=%%a
Это очень просто. for
без параметров считает пробелы разделителями; установка "*" в качестве tokens
Параметр заставляет программу собрать все части строки, которые не являются пробелами, и поместить их в новую строку, в которую она вставляет свои собственные пробелы.
Мне пришлось создать функцию.
Используйте это как:
@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.
Я использую "Trim Right Whitespace", точно работая над моим "Show-Grp-of-UID.CMD".:) Другие идеи для улучшения приветствуются.. ^_^