Мне нужно перебрать каждое слово в строке текста и получить последнее слово.
Для этого я использую следующий код.
for %%a in (%_IFLE_input%) do ( set _IFLE_last_token=%%a )
_IFLE_last_token=
теперь содержит последнее слово.
Однако я просто нажал слово, содержащее символ )
, и это остановило скрипт с ошибкой.
Close) was unexpected at this time.
Текст был Left)Close
Я попытался поместить входную переменную в кавычки
for %%a in ("%_IFLE_input%") do ( set _IFLE_last_token=%%a )
Но тогда %%a
— это просто вся строка, пробелы и все такое.
Есть ли правильный способ заключить строку в кавычки, чтобы for проходил каждое слово, но не нарушая синтаксис цикла for для таких символов, как )
?
Единственный вариант, который я вижу, - это отфильтровать все ядовитые символы, а затем разбить их на пробелы.
Есть ли лучший способ, в пакетном режиме? (Или с помощью внешних инструментов, доступных для необновленной Windows 10 22h2)
Да, powershell будет для /f "usebackq tokens=*" %%a в (powershell -command "'%_IFLE_input%'.Split(' ')[-1]"
) do set _IFLE_last_token=%%a, но я хочу сделать это в чистом пакете
Ну, вы сказали: «Или с помощью внешних инструментов, доступных для необновленной Windows 10 22h2», в которую входит PowerShell. Ваши требования полностью определяются вами.
Вы правы, powershell — один из них. Я спросил неточно. Я имел в виду такие инструменты, как findstr, fc или certutil. Вещи, которые все еще могут работать на dos 6.22 или win95.
вы действительно ожидаете, что findstr.exe
или certutil.exe
будут существовать в DOS или Win95? Если вам нужна максимальная (теоретическая) совместимость, возможно, вам следует установить планку XP или 2000. Что-нибудь до этого, и вы даже не можете ожидать, что cmd.exe
будет вести себя так же.
Вы правы, я попробовал Win95 cmd, и даже длинные имена меток, которые я использую, не работают. Мне интересно, можно ли перенести cmd.exe и другие .exe из w2k обратно в win9x. Я видел, как кто-то заставлял dotnet работать на Win95, так что, возможно, это возможно. Но да, таргетинг на w2k более разумен. Я также предпочитаю использовать скрипт в чистом пакете. Я нахожу их менее пугающими для совместного использования, чем powershell, плюс вероятность того, что групповые политики будут останавливать выполнение пакетных файлов, меньше, чем powershell, на компьютерах только для пользователей.
Другой способ обработки проблемной строки — отложенное расширение (переменная расширяется после анализа строки, что предотвращает синтаксическую ошибку.
@echo off
setlocal enabledelayedexpansion
set "var=Left)Close"
for %%a in (!var!) do ( set "last=%%a" )
set last
Примечание: таким образом могут возникнуть проблемы, если строка содержит один или несколько !
.
Когда вы говорите о «каждой строке текстового файла»:
@echo off
setlocal enabledelayedexpansion
set "var=Left!Close"
for /f "delims = " %%x in (test.txt) do (
for %%a in (%%x) do ( set "last=%%a" )
echo !last!
)
Спасибо, это работает. Я считаю, что это «стандартный» ответ, и принимаю его. Однако ответ @squashman более впечатляющий. Жаль, что я не могу принять оба с комментариями
SET "last=%%~a"
Этот неуклюжий синтаксис позволяет (пытаться) запретить cmd.exe обрабатывать данные в %%a
как код. ~
удаляет окружающие кавычки из %%a
, что является гарантией при использовании кавычек для защиты содержимого переменной.
Даже это не защитит вас от всех специальных символов постоянно. cmd.exe имеет некоторые серьезные ограничения при обработке текста и строк, и это одно из них.
Вот метод, который использует подстановку строк для присвоения первого и последнего слова переменным. При необходимости код можно расширить, чтобы присвоить каждое слово массиву переменных.
@echo off & setlocal
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=6429
set "_IFLE_input=A long sentence) with lots of word(s) and stuff!"
set "_IFLE_first_token=%_IFLE_input: = " & set "_IFLE_last_token=%"
echo First word: %_IFLE_first_token%
echo Last word: %_IFLE_last_token%
endlocal
Выход
D:\My Drive\BatchFiles\SO\78389129>so.bat
First word: A
Last word: stuff!
Другой вариант — заключить каждый термин, разделенный пробелами, в кавычки.
@echo off & setlocal
set "_IFLE_input=A long sentence) with lots of word(s) and stuff!"
for %%G in ("%_IFLE_input: = " "%") do ( set _IFLE_last_token=%%~G )
echo Last word: %_IFLE_last_token%
endlocal
Выход
D:\My Drive\BatchFiles\SO\78389129>so3.bat
Last word: stuff!
Спасибо, что указали на это. Это волшебство все еще выше моей зарплаты! Но я подтверждаю, что все работает отлично! Интересно, смогу ли я построить из них правильные функции объединения и разделения!
Есть ли у сообщества программистов пакетных файлов название для этого метода?
@Shodan это базовая замена строк.
Я имею в виду, что это нечто большее: при подмене выполняется внедрение команд. %_IFLE_input: = " и установите "_IFLE_last_token=%
Я имею в виду следующее, в частности %_IFLE_input: = " & set "_IFLE_last_token=%
PowerShell входит в стандартную комплектацию компьютеров под управлением Windows и может делать все, что вы хотите, без проблем, связанных с отсутствием в cmd различия между данными и кодом.