1

Тема: CMD/BAT: смена регистра строки текста

В обсуждение этой темы: http://forum.script-coding.com/viewtopic.php?id=3375

Предлагаю альтернативный способ преобразования строки к верхнему регистру:

@ echo off
setlocal enabledelayedexpansion

set strText=Hello, World
echo %strText%
call :UpperCase "%strText%" "strText"
echo UpperCase: %strText%

pause
exit /b 0

:UpperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
setlocal
set tempFile=temp.~txt
find "" "*:%~1" 2>%tempFile%
for /f "tokens=1,2* delims=:" %%a in (%tempFile%) do set strTempString=%%c
del /q %tempFile%
endlocal & set %~2=%strTempString%
exit /b 0

Преимущество метода: существенно меньше кода.
Недостаток метода: данные прогоняются через временный файл. Интересно, можно ли от этого избавиться?

2 (изменено: wisgest, 2013-01-01 15:31:07)

Re: CMD/BAT: смена регистра строки текста

Интересное, неожиданное решение. Хотя и несколько (не знаю, как правильно сказать) «нерегулярное» — не уверен, что можно ожидать его стабильную работу во всех версиях FIND.EXE. Но, думаю, Коллекцию этим решением можно будет дополнить…

Arigato пишет:

Недостаток метода: данные прогоняются через временный файл. Интересно, можно ли от этого избавиться?

for /f "tokens=1,2* delims=:" %%a in ('find "" "*:%~1" 2^>^&1') do set strTempString=%%c

— но проверьте, нет ли в этом каких-либо подводных камней.

3 (изменено: Arigato, 2013-01-01 17:04:49)

Re: CMD/BAT: смена регистра строки текста

Что-то не догадался, что надо экранировать символы под for.

Подводные камни имеются, не любая строка будет корректно обработана. Т.к. там строка воспринимается как имя файла, то, почему-то, код зависает, если в строке есть символы * или ?, которые являются масками (но это после двоеточия, которое воспринимается как имя диска).

P.S. Как ни странно, проблема быстро решилась

@ echo off
setlocal enabledelayedexpansion

set strText=Hello, World?
echo %strText%
call :UpperCase "%strText%" "strText"
echo UpperCase: %strText%

pause
exit /b 0

:UpperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
setlocal
for /f "tokens=1,2* delims=:" %%a in ('find "" "%~1:~~~" 2^>^&1') do set strTempString=%%b
endlocal & set %~2=%strTempString%
exit /b 0

Пока других подводных камней не обнаружил.

Чисто теоретически код не сработает, если подставить строку, скажем, "C", при этом на диске "C:" будет файл "~~~" в корне

4

Re: CMD/BAT: смена регистра строки текста

Arigato пишет:

Чисто теоретически код не сработает, если подставить строку, скажем, "C", при этом на диске "C:" будет файл "~~~" в корне

Вместо «~~~» можно использовать «NUL» или даже «.».

Arigato пишет:

P.S. Как ни странно, проблема быстро решилась

А если в строке будет двоеточие? По-моему, будет потеряно всё что идёт за ним (вероятно, надо использовать TOKENS=1* и отбрасывать n последних символов strTempString).

5 (изменено: Arigato, 2013-01-01 18:55:44)

Re: CMD/BAT: смена регистра строки текста

Можно использовать точку. Точка всегда существует на диске, но команда FIND на нее ругается: "Нет доступа: C:\." Так что она тоже подойдет.
На счет двоеточий в строке, верное замечание. И так, переделанный вариант:

@ echo off
setlocal enabledelayedexpansion

set strText=Hello, World?
echo %strText%
call :UpperCase "%strText%" "strText"
echo UpperCase: %strText%

pause
exit /b 0

:UpperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
setlocal
for /f "tokens=1* delims=:" %%a in ('find "" "%~1:." 2^>^&1') do set strTempString=%%b
endlocal & set %~2=%strTempString:~0,-2%
exit /b 0

P.S. Если встречается двоеточие, то все равно результат неверный. Например, для "Hello: World" теперь работает правильно, но "Hello: World?" неверно, т.к. вернулись к исходной проблеме, когда символы маски в имени файла. Надо еще думать над проблемой...

6 (изменено: Arigato, 2013-01-01 19:08:00)

Re: CMD/BAT: смена регистра строки текста

Нашел еще одну проблему: появляется пробел в начале строки. Эта проблема успешно решена.
Проблема с двоеточием решена таким образом: заменяем все двоеточия в исходной строке на непечатный символ (я меняю его на BEEP), после FIND делаем обратную замену: этот символ на двоеточие. Пока проблем не нашел, тестируем дальше.

Код:

@ echo off
setlocal enabledelayedexpansion

set strText=*** Hello: World? ***
echo %strText%
call :UpperCase "%strText%" "strText"
echo UpperCase: %strText%

pause
exit /b 0

:UpperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
setlocal
set strTempString=%~1
set strTempString=%strTempString::=%
for /f "tokens=1,2* delims=:" %%a in ('find "" "%strTempString%:." 2^>^&1') do set strTempString=%%b
set strTempString=%strTempString:=:%
endlocal & set %~2=%strTempString:~1%
exit /b 0

P.S. Учитывая наличие непечатных символов в коде, качаем код из аттача, т.к. на форуме эти символы исчезли.

Post's attachments

uppercase.cmd 671 b, 5 downloads since 2013-01-01 

You don't have the permssions to download the attachments of this post.

7 (изменено: wisgest, 2013-01-01 20:08:07)

Re: CMD/BAT: смена регистра строки текста

А если так (при желании перед «:» можно добавить «*», а после «\» — «nul», «.» или, в принципе, что угодно):

for /f "tokens=2* delims=:" %%a in ('find "" ":%~1\" 2^>^&1') do set strTempString=%%b
endlocal & set %~2=%strTempString:~0,-1%

?

(ENABLEDELAYEDEXPANSION пока не используется, а восклицательные знаки съедает.)

8

Re: CMD/BAT: смена регистра строки текста

На первый взгляд работает. Т.е. все проблемы, только если символы маски появляются в имени файла, в пути они к проблемам вроде не приводят.

Тогда пока остановимся на таком варианте:

@ echo off
setlocal enabledelayedexpansion

set strText=*** Hello: World? ***
echo %strText%
call :UpperCase "%strText%" "strText"
echo UpperCase: %strText%

pause
exit /b 0

:UpperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
setlocal
set strTempString=%~1
for /f "tokens=2* delims=:" %%a in ('find "" ":%~1\" 2^>^&1') do set strTempString=%%b
endlocal & set %~2=%strTempString:~0,-1%
exit /b 0

Восклицательный знак вообще не понятно, как вывести из переменной.
Так выводит:

echo Hello, World^^!

А так нет:

set str=Hello, World^^!
echo %str%

Единственное, как удалось его вывести:

set str=Hello, World^^^^^^^^^^!
echo %str%

Надо бы осмыслить эту конструкцию Меньшее количество крышечек не помогает. Однако если прогнать такую строку через :UpperCase, то восклицательный знак исчезнет.

9

Re: CMD/BAT: смена регистра строки текста

Arigato пишет:

Тогда пока остановимся на таком варианте:

Похоже, что можно было бы ограничится лишь косой чертой,
но, впрочем, двоеточие не мешает, т.к. упрощает разбор вывода на части.

Вопрос о восклицательном знаке — отдельная тема , так что можно в неё здесь не углубляться.
Впрочем, она снимается, если убрать ENABLEDELAYEDEXPANSION после SETLOCAL, т.к. отложенная подстановка в этом примере всё равно не применяется.
(С другой стороны, может быть, она могла бы как-то облегчить борьбу с управляющими знаками вроде &><… в преобразуемой строке, если всё-таки использовать вспомогательный временный файл и читать его не через FOR/F, а через SET/P?)

Если не будет каких-либо замечаний и предложений, то завтра-послезавтра добавлю в Коллекцию в текущем виде (без ENABLEDELAYEDEXPANSION).

10

Re: CMD/BAT: смена регистра строки текста

wisgest пишет:

С другой стороны, может быть, она могла бы как-то облегчить борьбу с управляющими знаками вроде &><… в преобразуемой строке, если всё-таки использовать вспомогательный временный файл и читать его не через FOR/F, а через SET/P?

Лучше не прогонять данные через файлы. Задача преобразовать строку текста к верхнему регистру, ради этого использовать механику жесткого диска кажется избыточным.

11

Re: CMD/BAT: смена регистра строки текста

Добавил.

12 (изменено: urahangka, 2013-04-02 16:59:30)

Re: CMD/BAT: смена регистра строки текста

Кстати, а такой вариант чем плох?
кодировка ДОС (866)


@echo off
set str=мама мыла раму!
echo %str%
call :toUpper str
echo %str%
pause
exit /b

:toUpper str -- преобразование нижнего регистра к верхнему
if not defined %~1 EXIT /b
for %%a in ("a=A" "b=B" "c=C" "d=D" "e=E" "f=F" "g=G" "h=H" "i=I"
            "j=J" "k=K" "l=L" "m=M" "n=N" "o=O" "p=P" "q=Q" "r=R"
            "s=S" "t=T" "u=U" "v=V" "w=W" "x=X" "y=Y" "z=Z" "?=?"
            "?=?" "?=?" "а=А" "б=Б" "в=В" "г=Г" "д=Д" "е=Е" "ё=Ё" 
            "ж=Ж" "з=З" "и=И" "й=Й" "к=К" "л=Л" "м=М" "н=Н" "о=О"
            "п=П" "р=Р" "с=С" "т=Т" "у=У" "ф=Ф" "х=Х" "ц=Ц" "ч=Ч"
            "ш=Ш" "щ=Щ" "ъ=Ъ" "ы=Ы" "ь=Ь" "э=Э" "ю=Ю" "я=Я" ) do (
    call set %~1=%%%~1:%%~a%%
)
EXIT /b

Соответственно, преобразование верхнего к нижнему по аналогии.

Прикрепил файл, так как не все символы читабельны

Post's attachments

toUpper.cmd 670 b, 6 downloads since 2013-04-02 

You don't have the permssions to download the attachments of this post.

13 (изменено: smaharbA, 2013-05-22 22:09:54)

Re: CMD/BAT: смена регистра строки текста

если уж нужна отложенная обработка

@ echo off
set "strText=*** Hello, World! ***"
set "strText=%strText:!=?%
setlocal enabledelayedexpansion
echo %strText%
call :UpperCase "!strText!" "strText"
endlocal & set out=UpperCase: %UpperCase:?=!%
echo %out%

pause
exit /b 0

:UpperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
setlocal
set out=%~0
set strTempString=%~1
for /f "tokens=2* delims=:" %%a in ('find "" ":%~1\" 2^>^&1') do set strTempString=%%b
endlocal & set %out:~1%=%strTempString:~0,-1%
exit /b 0

знак вопроса это альт+12

да, автор идея интересная, как говорят "пеши исчо!" )

Я конечно далек от мысли... (с)

14

Re: CMD/BAT: смена регистра строки текста

urahangka пишет:

Кстати, а такой вариант чем плох?
кодировка ДОС (866)

Хороший вариант. Предлагаю его немного упростить:

@echo off
setlocal enabledelayedexpansion
set str=мама мыла раму, hello World
for %%a in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я) do set str=!str:%%a=%%a!
echo %str%
pause

Это просто пример, без функции.

15 (изменено: Arigato, 2013-10-26 18:44:46)

Re: CMD/BAT: смена регистра строки текста

Пожалуй, это лучший вариант для преобразования регистров символов:

:upperCase
:: Преобразование текстовой строки к верхнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
  setlocal
  set strTemp=%~1
  for %%a in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я) do set strTemp=!strTemp:%%a=%%a!
  endlocal & set %~2=%strTemp%
exit /b 0

:lowerCase
:: Преобразование текстовой строки к нижнему регистру
:: %1 - исходная строка
:: %2 - переменная для записи результата
  setlocal
  set strTemp=%~1
  for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я) do set strTemp=!strTemp:%%a=%%a!
  endlocal & set %~2=%strTemp%
exit /b 0

Пример в аттаче.

Post's attachments

chcase.zip 622 b, 9 downloads since 2013-10-26 

You don't have the permssions to download the attachments of this post.