Как разбить строку без цикла в пакетном файле
Я хочу разбить строку на две части, не используя цикл for.
Например, у меня есть строка в переменной:
str=45:abc
Я хочу получить 45
в переменной и abc
в другой переменной. Возможно ли это в пакетном файле?
шаблон похож на somenumber: somestring
Ответы
Ответ 1
Вы можете разделить str разными способами.
Цикл for, вы не хотите его использовать.
Заключительная часть легко с *
(соответствовать чему угодно до...)
set "var2=%str:*:=%"
Ведущую роль можно сделать с неприятным трюком
set "var1=%str::="^&REM #%
Для выхода из амперсанда требуется каретка,
поэтому эффектно двоеточие будет заменено на "&REM #
Таким образом, в вашем случае вы получили строку после замены
set "var1=4567"&REM #abcde
И это разделено на две команды
set "var1=4567"
REM #abcde`
И полный код здесь:
set "str=4567:abcde"
echo %str%
set "var1=%str::="^&REM #%
set "var2=%str:*:=%"
echo var1=%var1% var2=%var2%
Изменить 2: Более стабильная ведущая часть
Спасибо Дэйву за идею использования перевода строки.
Технология REM не очень устойчива к контенту с кавычками и специальными символами.
Но с трюком перевода строки существует более стабильная версия, которая также работает, когда аргумент split больше, чем один символ.
@echo off
setlocal enableDelayedExpansion
set ^"str=456789#$#abc"
for /F "delims=" %%a in (^"!str:#$#^=^
!^") do (
set "lead=%%a"
goto :break
)
:break
echo !lead!
Решение 3: Ответный ответ dbenhams
Dbenham использует в своем решении линию с трубой.
Это кажется немного сложнее.
Поскольку решение использует тот факт, что синтаксический анализатор удаляет оставшуюся часть строки после необработанного перевода строки (когда это обнаружено до или в фазе специального символа).
Сначала символ двоеточия заменяется на строку с задержкой замены.
Это разрешено, и строка перевода теперь является частью переменной.
Затем линия set lead=%lead%
разделяет конечную часть.
Лучше не использовать расширенный синтаксис здесь, так как set "lead=%lead%"
будет ломаться, если цитата является частью строки.
setlocal enableDelayedExpansion
set "str=45:abc"
set ^"lead=!str::=^
!"
set lead=%lead%
echo "!lead!"
Ответ 2
Вы можете попробовать это. Если зафиксировано, что числа слева от двоеточия будут всегда 2, а справа будет 3. Затем следующий код должен работать, если ваша str имеет значение.
set "str=45:abc"
echo %str%
set var1=%str:~0,2%
set var2=%str:~3,3%
echo %var1% %var2%
Держи меня в курсе.:)
Ответ 3
Кажется бессмысленным избегать использования цикла FOR, но это делает проблему интересной.
Как отметил Джеб, получение конечной части легко с помощью !str:*:=!
.
Трудный бит - ведущая часть. Вот альтернатива решению jeb.
Вы можете вставить строку в переменную вместо :
, используя следующий синтаксис
setlocal enableDelayedExpansion
set "str=45:abc"
echo !str::=^
!
- ВЫВОД -
45
abc
Неверная строка выше последнего !
.
Я не уверен, почему, но когда вывод вышеперечисленного передан в команду, сохраняется только первая строка. Таким образом, вывод может быть передан в FINDSTR, который соответствует любой строке, и этот результат направлен на файл, который затем может быть прочитан в переменную с помощью SET/P.
2-я строка должна быть устранена до использования SET/P, потому что SET/P не распознает <LF>
как ограничитель строки - он распознает только <CR><LF>
.
Вот полное решение:
@echo off
setlocal enableDelayedExpansion
set "str=45:abc"
echo(!str::=^
!|findstr "^" >test.tmp
<test.tmp set /p "var1="
del test.tmp
set "var2=!str:*:=!"
echo var1=!var1! var2=!var2!
Обновление
Я полагаю, что я в основном понял, почему вторая строка лишена выхода:)
Это связано с тем, как обрабатываются трубы Windows cmd.exe с каждой стороны, обрабатываемой новым потоком CMD.EXE. См. Почему задержка с расширением заканчивается, когда внутри кода блока кода? для связанного вопроса с отличным ответом от jeb.
Просто глядя на левую сторону команды piped, я считаю, что она разбирается (в памяти) в выражение, которое выглядит как
C:\Windows\system32\cmd.exe /S /D /c" echo {delayedExpansionExpression}"
Я использую {delayedExpansionExpression}
для представления многострочного поиска и замены расширения, которое еще не произошло.
Далее, я думаю, что выражение переменной фактически расширилось, и строка была разбита на два путем поиска и замены:
C:\Windows\system32\cmd.exe /S /D /c" echo 43
abc"
Только тогда выполняется команда, а по нормальным правилам cmd.exe команда заканчивается на линии. В цитируемой командной строке отсутствует конечная цитата, но парсер не заботится об этом.
Часть, которую я все еще озадачен, что происходит с abc"
? Я бы подумал, что для его выполнения будет предпринята попытка, в результате чего сообщение об ошибке, такое как "abc", не будет распознано как внутренняя или внешняя команда, операционная программа или командный файл. кажется, просто теряется в эфире.
note - jeb 3rd comment объясняет, почему:)
Безопасная версия без FOR
Мое первоначальное решение не будет работать со строкой типа this & that:cats & dogs
. Ниже приведен вариант без FOR, который должен работать практически с любой строкой, за исключением ограничений длины строки, а конечные контрольные символы будут удалены из ведущей части.
@echo off
setlocal enableDelayedExpansion
set "str=this & that:cats & dogs"
set ^"str2=!str::=^
!^"
cmd /v:on /c echo ^^!str2^^!|findstr /v "$" >test.tmp
<test.tmp set /p "var1="
del test.tmp
set "var2=!str:*:=!"
echo var1=!var1! var2=!var2!
Я задерживаю расширение до нового потока CMD, и я использую причуду регулярного выражения FINDSTR, что $
соответствует только строкам, заканчивающимся <cr>
. Первая строка не имеет его, а вторая -. Опция /v
инвертирует результат.
Ответ 4
Да, я знаю, что это очень старая тема, но я только что ее обнаружил, и я не могу устоять перед соблазном опубликовать свое решение:
@echo off
setlocal
set "str=45:abc"
set "var1=%str::=" & set "var2=%"
echo var1="%var1%" var2="%var2%"
Вы можете прочитать полную информацию об этом методе здесь.
Ответ 5
Здесь решение без неприятных трюков для ведущей части
REM accepts [email protected]
setlocal enableDelayedExpansion
set "str=%1"
set "host=%str:*@=%"
for /F "tokens=1 [email protected]" %%F IN ("%str%") do set "user=%%F"
echo [email protected] = %user%@%host%
endlocal
Ответ 6
В свете людей, публикующих всевозможные метафоры для разделения переменных здесь, я мог бы также опубликовать свой собственный метод, разрешив не только один, но несколько переменная, обозначенная тем же символом, что невозможно с помощью REM-метода (который я использовал в течение некоторого времени, спасибо @jeb).
С помощью приведенного ниже метода строка, определенная во второй строке, разбивается на три части:
setlocal EnableDelayedExpansion
set fulline=one/two/three or/more
set fulline=%fulline%//
REM above line prevents unexpected results when input string has less than two /
set line2=%fulline:*/=%
set line3=%line2:*/=%
set line1=!fulline:/%line2%=!
set line2=!line2:/%line3%=!
setlocal DisableDelayedExpansion
echo."%line1%"
echo."%line2%"
echo."%line3%"
ВЫВОД:
"one"
"two"
"three or/more//"
Я рекомендую использовать последний так называемый раздел строки как "bin" для оставшихся "безопасных" разделяемых символов.