1

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

Здравствуйте.

Я дико извиняюсь за предположительно идиотские вопросы, но самостоятельный поиск результатов не приносит. Я честно старался полдня, читал документацию и примеры, прилично обогатил жизненный опыт, но ответа так и не нашёл.
Неясности таковы:

1. В скрипте есть такие строки:

set connection=Megafon
...
if "%%i"=="%connection:"=%" set connected=1

Непонятен смысл конструкции "%connection:"=%". Конструкция "%connection%" работает вполне адекватно.

2. В скрипте есть такие строки:

FOR /F "tokens=1,2* delims=:" %a in ('ipconfig^|FIND "IP-"') do @ECHO %b

Непонятен смысл конструкции ('ipconfig^|FIND "IP-"'). Каретка явно меняет поведение выражения, но почему - не пойму. Более того, поведение отдельной команды ipconfig тоже меняется при запуске ее с кареткой, в виде ipconfig^. То есть, налицо какие-то неочевидные мне функции каретки. Плюс, не получается четко уловить отличие между двойными и одинарными кавычками.

3. Вопрос несколько не в тему: при попытке найти ответы на вышеизложенные вопросы я столкнулся с тем, что гугль и яндекс не осуществляют поиск по спецсимволам. Экранировать их никак не получается, в документации к поисковым машинам тоже ничего на этот счёт не сказано.

Может быть, кого-нибудь не затруднит помочь мне?

2

Re: CMD/BAT: неясности синтаксиса

fsc_psd, надо было дополнительно привести весь скрипт целиком. Сделайте это, пожалуйста. Код на форуме оформляется тэгом «code», я поправил.

3

Re: CMD/BAT: неясности синтаксиса

fsc_psd пишет:

2. В скрипте есть такие строки:

FOR /F "tokens=1,2* delims=:" %a in ('ipconfig^|FIND "IP-"') do @ECHO %b

Непонятен смысл конструкции ('ipconfig^|FIND "IP-"'). Каретка явно меняет поведение выражения, но почему - не пойму. Более того, поведение отдельной команды ipconfig тоже меняется при запуске ее с кареткой, в виде ipconfig^. То есть, налицо какие-то неочевидные мне функции каретки.

«|» — спецсимвол, потому в выражении «FOR /F … ('ipconfig|FIND "IP-"') do…» рассматривается не как часть вложенной команды «ipconfig|FIND "IP-», а как часть внешней команды «for /f…», вследствие чего получается не то, что нужно, а ошибка. Посему подобные спецсимволы в подобных случаях требуют экранирования: Как экранировать символ?. Ну, и, вообще, рекомендуется ознакомиться с CMD/BAT: Коллекция ссылок.

Что именно неясно в:

fsc_psd пишет:

Плюс, не получается четко уловить отличие между двойными и одинарными кавычками.

4

Re: CMD/BAT: неясности синтаксиса

Скрипт из первого вопроса:

@set @x=0 /*
@echo off 
:_start 
start "" "C:\Program Files\3G Modem Manager\3G Modem Manager.exe" 
cscript //nologo /e:jscript "%~f0" 200000 
rasdial Night UserName UserPwd 
:_prv_soed 
set my_full_time=%TIME% 
IF %my_full_time:~0,1%==0 ( 
   set my_house=%my_full_time:~1,1% 
   ) else ( 
   set my_house=%my_full_time:~0,2% 
   ) 
IF %my_full_time:~3,1%==0 ( 
   set my_min=%my_full_time:~4,1% 
   ) else ( 
   set my_min=%my_full_time:~3,2% 
   ) 
if %my_house% GEQ 7 (if %my_min% GEQ 55 (goto :_Kill_all)) 
cscript //nologo /e:jscript "%~f0" 60000 
Ping -n 1 ya.ru >Nul 
if ErrorLevel 1 GoTo :_Kill_Proc 
if ErrorLevel 0 GoTo :_prv_soed 
:_Kill_proc 
rasdial Night /Disconnect 
cscript //nologo /e:jscript "%~f0" 60000 
Taskkill /F /IM "3G Modem Manager.exe" 
cscript //nologo /e:jscript "%~f0" 60000 
goto :_start 
:_Kill_all 
rasdial Night /Disconnect 
cscript //nologo /e:jscript "%~f0" 60000 
Taskkill /F /IM "3G Modem Manager.exe" 
goto:eof */ if(isFinite(WScript.Arguments(0))) WScript.Sleep(WScript.Arguments(0))

Насчёт насчёт каретки во втором скрипте ситуация, похоже, отчасти прояснилось - я и правда затупил с экранированием - но меня крепко ввело в сомнение, что каретка меняет поведение отдельной одиночной команды - ipconfig. Почему так?

По поводу кавычек - я просто не обнаружил связного объяснения их функций и отличий друг от друга. Во втором примере фигурируют оба типа кавычек и закономерности их употребления слегка загадочны.

5

Re: CMD/BAT: неясности синтаксиса

fsc_psd пишет:

Скрипт из первого вопроса…

И где тут приведённые Вами строки в #1?! Что-то не то.

fsc_psd пишет:

1. В скрипте есть такие строки:

set connection=Megafon
...
if "%%i"=="%connection:"=%" set connected=1

Непонятен смысл конструкции "%connection:"=%". Конструкция "%connection%" работает вполне адекватно.

set /? пишет:


Подстановка переменной среды может быть расширена следующим образом:

%PATH:str1=str2%

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

То есть, в данном случае «%connection:"=%» означает — взять содержимое переменной окружения «connection» и убрать из него все включения кавычки «"» (поскольку после знака равенства в выражении ничего нет).

fsc_psd пишет:

…но меня крепко ввело в сомнение, что каретка меняет поведение отдельной одиночной команды - ipconfig. Почему так?

Нет, не меняет. Символ «^» воздействует только на восприятие интерпретатором командного процессора следующего за ним спецсимвола «|», дабы последний воспринимался не как спецсимвол конвейера, а как обычный символ (а вот когда интерпретатор «развернёт» строку «'ipconfig^|FIND "IP-"'» и начнёт обрабатывать саму последовательность команд «ipconfig|FIND "IP-"» — вот тогда символ «|» будет уже правильно воспринят как спецсимвол конвейера).

fsc_psd пишет:

Во втором примере фигурируют оба типа кавычек

Приведите конкретный короткий пример, я уже запутался.

6

Re: CMD/BAT: неясности синтаксиса

Доброго утра!
Ещё раз извиняюсь - голова вчера была чугунная, попутал, видать, версии скрипта. Вот тот, о котором шла речь:

@echo off
set connection=Megafon
set time_a1=" 1:10:00,00"
set time_a2=" 7:50:00,00"
 :LOOP
set connected=0
for /f "delims=" %%i in ('rasdial') do (
    if "%%i"=="%connection:"=%" set connected=1
)
    if    %connected%==0 (
    if /i "%time%" geq %time_a1% (
    if /i "%time%" leq %time_a2% (
          goto CONNECTING
                      )))
    if    %connected%==1 (
    if /i "%time%" geq %time_a1% (
    if /i "%time%" leq %time_a2% (
          goto CONNECTED
                      )))
    if    %connected%==0 (
          goto DISCONNECTED
                         )
    if    %connected%==1 (
          goto DISCONNECTING
                         )
goto TIMEOUTing
:CONNECTING
    echo %time% - "%connection%" connection not detected.
    echo Dialing...
    rasdial "%connection:"=%"
    goto TIMEOUTing
:CONNECTED    
    echo %time% - "%connection%" connected
    goto TIMEOUTing
:DISCONNECTING
    echo %time% - "%connection%" connection is active.
    echo "%connection%" are disconnecting...
    rasdial "%connection:"=%" /DISCONNECT
    goto TIMEOUTing
:DISCONNECTED
    echo %time% - "%connection%" disconnected
    goto TIMEOUTing
:TIMEOUTing
timeout /T 27
goto LOOP

То есть, в данном случае «%connection:"=%» означает — взять содержимое переменной окружения «connection» и убрать из него все включения кавычки «"» (поскольку после знака равенства в выражении ничего нет).

Да, похоже именно так. Спасибо большое! Наверное, в одном из предыдущих вариантов скрипта кавычки там могли появляться от случая к случаю, да?. Вчера это мне оказалось не по зубам.

Нет, не меняет.

Всё-таки меняет. Я даже на другом виндовсе сейчас попробовал. Итого и на XP и на 2003 команда "ipconfig^" ведёт себя так: прежде чем выдать справку ipconfig интерпретатор два раза запрашивает "Продолжить?" Все, что будет введено в этом диалоге, дополнит название команды, т.е. если ответить "123", то будет предпринята попытка выполнить "ipconfig123". Если нажать enter, то запрос повторится, а после второго пустого ответа будет выполнена просто команда "ipconfig". Каретка явно тут как-то замешана, вот я и подумал, что у нее есть ещё какие-то функции, мне неизвестные.

а вот когда интерпретатор «развернёт» строку «'ipconfig^|FIND "IP-"'» и начнёт обрабатывать саму последовательность команд «ipconfig|FIND "IP-"» — вот тогда символ «|» будет уже правильно воспринят как спецсимвол конвейера.

Вас понял, большое спасибо! Скажите, пожалуйста, а почему при втором проходе интерпретатор уже не будет учитывать символ каретки в качестве экрана для спецсимвола контейнера?

Приведите конкретный короткий пример, я уже запутался.

Я, на самом деле, даже не за пример переживаю, а просто не смог найти внятную информацию о правилах употребления одинарных кавычек. С двойными вроде всё более-менее понятно. В качестве конкретного короткого примера можно взять «'ipconfig^|FIND "IP-"'» из прошлого вопроса. С его помощью я теперь, конечно, сориентировался, что к чему, но хотелось бы почитать полный свод правил, касающийся одинарных кавычек и их отличий от двойных.

7

Re: CMD/BAT: неясности синтаксиса

fsc_psd пишет:

Наверное, в одном из предыдущих вариантов скрипта кавычки там могли появляться от случая к случаю, да?

Думаю, так.

fsc_psd пишет:
alexii пишет:
fsc_psd пишет:

…но меня крепко ввело в сомнение, что каретка меняет поведение отдельной одиночной команды - ipconfig. Почему так?

Нет, не меняет…

Всё-таки меняет. Я даже на другом виндовсе сейчас попробовал. Итого и на XP и на 2003 команда "ipconfig^" ведёт себя так…

Не меняет. Вы невнимательно ознакомились с приведённой выше в посте #3 ссылкой, ибо следующий же раздел: Как перенести длинную строку?, как раз объясняет данное поведение — в интерактивном режиме интерпретатор командного процессора просто ожидает продолжения ввода команды на новой строке (что Вы, собственно, и описали).

fsc_psd пишет:

…а почему при втором проходе интерпретатор уже не будет учитывать символ каретки в качестве экрана для спецсимвола контейнера?

Данный спецсимвол после обработки удаляется интерпретатором командного процессора. Потому ко второму проходу строка придёт в требуемом нам виде — «ipconfig|FIND "IP-"».

fsc_psd пишет:

Я, на самом деле, даже не за пример переживаю, а просто не смог найти внятную информацию о правилах употребления одинарных кавычек. С двойными вроде всё более-менее понятно. В качестве конкретного короткого примера можно взять «'ipconfig^|FIND "IP-"'» из прошлого вопроса. С его помощью я теперь, конечно, сориентировался, что к чему, но хотелось бы почитать полный свод правил, касающийся одинарных кавычек и их отличий от двойных.

Тут песня интересная. В данном случае («for …») есть два поведения интерпретатора:

for /? пишет:


FOR /F ["ключи"] %переменная IN (набор) DO команда [параметры]
FOR /F ["options"] %variable IN ("literal string") DO command [command-parameters]
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]

    или, если использован параметр usebackq:

FOR /F ["options"] %variable IN (filenameset) DO command [command-parameters]
FOR /F ["options"] %variable IN ('literal string') DO command [command-parameters]
FOR /F ["options"] %variable IN (`command`) DO command [command-parameters]

т.е. — если не использован предикат «usebackq» — строка в одинарных кавычках рассматривается как команда (которую нужно выполнить, а вывод этой команды разобрать), если использован — то рассматривается как обычная строка.

В противоположность этому, строка в двойных кавычках — если не использован предикат «usebackq» — рассматривается как обычная строка, а если использован — то как набор обычный файлов (filenameset).

8

Re: CMD/BAT: неясности синтаксиса

Спасибо, Alexii !
Теперь всё совершенно понятно.

9

Re: CMD/BAT: неясности синтаксиса

Извините, но никак не догоню синтаксис выражения

if "%%i"=="%connection:"=%" set connected=1

.
А именно, вот этот кусок: %connection:"=%. Вижу, что происходит замена символов, но нигде в справке не смог отыскать информацию об операторе : (двоеточие).
Можно ли объяснить поподробнее, как это работает или кинуть ссылку описание этой конструкции?

10

Re: CMD/BAT: неясности синтаксиса

set /?

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

11

Re: CMD/BAT: неясности синтаксиса

Пост #5. Если Вы выполните команду:

set /?

сможете прочитать процитированный в том посте кусок подсказки.

12

Re: CMD/BAT: неясности синтаксиса

Спасибо!