TransWikia.com

Como setar variável utilizando substring em código batch (Windows CMD)

Stack Overflow em Português Asked by grmf on November 8, 2021

Fala galera,
To tentando gerar um código buscando parte do nome do serviço no Windows para setar em uma variável (ORACLE_SID).
Preciso fazer uma busca no serviço OracleService. Junto do nome tem o nome da base. Preciso pegar somente o nome da base.

Ex.:

OracleServiceXXX
OracleServiceYYY
OracleServiceZZZ

Tentei através do seguinte LOOP:

for /f "tokens=2" %s in ('sc query state^= all ^| find "OracleService"')

Tentei setar o valor com substring para a variável ORACLE_SID através de do set ORACLE_SID=%s:~13,20% , mas retorna desta forma:

set ORACLE_SID=OracleServiceXXX:~13,20% 
set ORACLE_SID=OracleServiceXXX:~13,20% 
set ORACLE_SID=OracleServiceYYY:~13,20% 
set ORACLE_SID=OracleServiceYYY:~13,20% 
set ORACLE_SID=OracleServiceZZZ:~13,20%
set ORACLE_SID=OracleServiceZZZ:~13,20%

Como faço para setar ORACLE_SID somente com a parte final do nome do serviço, e como faço pra ele retornar somente uma vez, sem repetir o mesmo valor ORACLE_SID anterior?

Ex do que preciso:

set ORACLE_SID=XXX
set ORACLE_SID=YYY
set ORACLE_SID=ZZZ

Valeu!!!

One Answer

*/ EDIT

Como faço para setar ORACLE_SID somente com a parte final do nome do serviço, e como faço pra ele retornar somente uma vez, sem repetir o mesmo valor ORACLE_SID anterior?

- Nota: A resposta abrange também outros pontos abordados em uma outra postagem do autor (já devidamente apagada pela moderação), onde nesta, têm-se um desvio do questionamento original a origem do 3º item abaixo listado/respondido

  • Obtenha sua substring na: 1ª ocorrência

  • Obtenha sua substring na: última ocorrência

  • Obtenha sua substring de: cada ocorrência



  • Obtenha sua substring de cada ocorrência    ⁄ ⁄  edit
@echo off

Setlocal EnableDelayedExpansion

pushd %__APPDIR__% && set "_svrc=OracleService"

for /f "tokens=*" %%s in ('sc query ^| find "_NAME:" ^| find /i "%_svrc%"')do ( 
     
     set /a "_cnt+=1+0" && set "_str=%%~s" && call set "_base_!_cnt!=!_str:*%_svrc%=!"
 
    )
    
if not defined _cnt (
      
      >nul chcp 65001
       echoServico %_svrc% não se encontra em execução
     
    ) else (
     
      for /L %%i in (1 1 !_cnt!)do call echoNome da Base: !_base_%%~i!

    )     

timeout.exe -1

popd
endlocal
  • Versão compacta e sem uso de "layout didático" no código:
@echo off && Setlocal EnableDelayedExpansion

set "_svrc=OracleService" & >nul chcp 65001 | pushd %__APPDIR__%
for /f tokens^=* %%s in ('sc.exe query^|find "_NAME:"^|find/i "%_svrc%"
')do set/a "_cnt+=1+0" && set "_str=%%~s" && call set "_base_!_cnt!=!_str:*%_svrc%=!"

if not defined _cnt (<con: echo=& echoServiço !_svrc! não foi encontrado em execução^!! 
)else for /L %%i in (1 1 !_cnt!)do set "_b=00%%~i" && call echoBase "!_b:~-2!": !_base_%%~i! 

timeout.exe /t -1 & popd | endlocal & goto=:EOF 

  • Obs.: 1 Para fins de testes estou substituindo OracleService por Windows, já que não tenho esse serviço em múltiplas ocorrências sendo executado.

  • 1. Sem qualquer manipulação por um loop for para o comando:
sc query | find "_NAME:" | find /i "windows"
  • A saída retorna dessa forma:
DISPLAY_NAME: Windows Audio Endpoint Builder
DISPLAY_NAME: Windows Audio
DISPLAY_NAME: Windows Event Log
DISPLAY_NAME: Windows Font Cache Service
DISPLAY_NAME: Windows Presentation Foundation Font Cache 3.0.0.0
DISPLAY_NAME: Windows Phone IP over USB Transport (IpOverUsbSvc)
DISPLAY_NAME: Windows License Manager Service
DISPLAY_NAME: Windows Defender Firewall
DISPLAY_NAME: Windows Security Service
DISPLAY_NAME: Windows Image Acquisition (WIA)
DISPLAY_NAME: Windows Biometric Service
DISPLAY_NAME: Windows Connection Manager
DISPLAY_NAME: Windows Defender Antivirus Network Inspection Service
DISPLAY_NAME: Windows Defender Antivirus Service
DISPLAY_NAME: Windows Management Instrumentation
DISPLAY_NAME: Windows Push Notifications System Service
DISPLAY_NAME: Windows Search
DISPLAY_NAME: Windows Push Notifications User Service_6a4f9
  • 2. Usando um loop for /f e contando as ocorrências para concatenar sua variável com o udo de um contador (set /a "_cnt+=1+0"), implementado de forma que permita salvar cada ocorrência em uma variável separadamente:
1º loop:
set _seu_contador=contador + 1   ⁄⁄  set /a _cnt=1+0          == set /a _cnt+=1+0
set _var_contador=1ª ocorrência  ⁄⁄  set /a _var_1=ocorrência == set_var_!_cnt!=1ª ocorrência

2º loop:
set _seu_contador=contador + 1   ⁄⁄  set /a _cnt=1+1+0        == set /a _cnt+=1+0
set _var_contador=2ª ocorrência  ⁄⁄  set /a _var_2=ocorrência == set_var_!_cnt!=2ª ocorrência

3º loop:
set _seu_contador=contador + 1   ⁄⁄  set /a _cnt=2+1+0        == set /a _cnt+=1+0
set _var_contador=3ª ocorrência  ⁄⁄  set /a _var_3=ocorrência == set_var_!_cnt!=3ª ocorrência

⁄⁄  Obs.: Como a variável _cnt não foi definida antes
⁄⁄        do 1º loop/uso, use '+0': set /a _cnt+=1+0
  • 3. As ações acima se darão (serão aplicadas) no processamento que retornar do loop For /F pelo comando sc query | find "_NAME:" | find /i "%_svrc%" (item 1.), adionando use um set _var=substring(%_var:removeSstring=%) para tratar na variavel o valor das strings que deseja remover/ficar. No seu caso caso, remover tudo que vem antes de OracleService e ficar com tudo que venha depois, seria:
set variavel=Remover Qualquer Strings Antes De OracleService Ficando Qualquer Strings Depois
set variavel=Remover Qualquer Strings Antes De OracleService 

set variavel=%variavel:*OracleService=%
set variavel=o seu valor mas tudo ("*") antes de 'OracleService' substituir ("=") por nada ("=%") 
set variavel=%variavel:*OracleService=%Ficando Qualquer Strings Depois
  • 4. Usando/aplicando para exemplo em um dos nomes na listagem dos serviços do Windows, como o Windows Update (veja Obs.: 1), resultaria em Update:
set variavel=%%~s
set variavel=Windows Update
set variavel=%variavel:*Windows`espaço!`=%

set variavel=%variavel:*Windows =%
set variavel=%variavel:*Windows Update
set variavel=Update

set "_svrc=Windows"
....

set "_str=Windows Update"
set "_base_!_cnt!=!_str:*Windows %=!" ⁄⁄ o mesmo que: set "_base_!_cnt!=Update"

set "_str=Windows Update"
set "_base_!_cnt!=!_str:*%_svrc%=!"  ⁄⁄ o mesmo que: set "_base_!_cnt!=*Windows Update"
  • 5. O mesmo contador !_cnt! incrementado no looping For /F, você pode usar para ober a listagem das ocorrências setadas/definas, basta fazer uso de um loop For /L, que dentro de um intervalo númerico pré definido para valor de início **1, valor de salto **1, e o valor de fim/final !_cnt!, de forma que todas as ocorrências/strings serão acessadas da mesma maneira com que foram definidas, usando concatenação:
For /L %%i in (1 1 !_cnt!)do... !_base_%%i!

⁄⁄ Existindo 3 ocorrências, o valor de !_cnt! será igual a 3, e loop 
⁄⁄ ficaria entre 1 e 3, pulando de 1 em 1: For /L %%i in (1 1 3,)do...  

For /L %%i in (1 1 !_cnt!)do... !_base_1! string na 1ª ocorrência/variável ⁄⁄ %%i == 1
                          do... !_base_2! string na 2ª ocorrência/variável ⁄⁄ %%i == 2
                          do... !_base_3! string na 3ª ocorrência/variável ⁄⁄ %%i == 3

For /L %%i in (1 1 !_cnt!)do... !_base_%%i! string na 1ª ocorrência/variável ⁄⁄ %%i == 1
                          do... !_base_%%i! string na 2ª ocorrência/variável ⁄⁄ %%i == 2
                          do... !_base_%%i! string na 3ª ocorrência/variável ⁄⁄ %%i == 3
  • 6. Apenas para fins de classificação e comparações nas execuções para testes, uma concatenação de dois zeros adicionada ao definir _b=%%i (set _b=00%%i), e na listagem fosse possível o uso de 02 dígitos, ao relacionar a saída dos serviços encontrados nas suas respectivas variáveis acessados pelo For /L, obtendo na listagem as bases com esse layout Base 01, ao invés de Base 01:

)else for /L %%i in (1 1 !_cnt!)do set "_b=00%%~i" && call echoBase "!_b:~-2!": !_base_%%~i! 
  • Lembrando da substuiçao de OracleService por Windows (vide Obs.: 1), e compare as stings na saída original do loop e nas alterações feitas com set string=substring:
  • ⇉ Saída Original
    sc query | find "_NAME:" | find /i "windows"
DISPLAY_NAME: Windows Audio Endpoint Builder
DISPLAY_NAME: Windows Audio
DISPLAY_NAME: Windows Event Log
DISPLAY_NAME: Windows Font Cache Service
DISPLAY_NAME: Windows Presentation Foundation Font Cache 3.0.0.0
DISPLAY_NAME: Windows Phone IP over USB Transport (IpOverUsbSvc)
DISPLAY_NAME: Windows License Manager Service
DISPLAY_NAME: Windows Defender Firewall
DISPLAY_NAME: Windows Security Service
DISPLAY_NAME: Windows Image Acquisition (WIA)
DISPLAY_NAME: Windows Biometric Service
DISPLAY_NAME: Windows Connection Manager
DISPLAY_NAME: Windows Defender Antivirus Network Inspection Service
DISPLAY_NAME: Windows Defender Antivirus Service
DISPLAY_NAME: Windows Management Instrumentation
DISPLAY_NAME: Windows Push Notifications System Service
DISPLAY_NAME: Windows Search
DISPLAY_NAME: Windows Push Notifications User Service_6a4f9
  • ⇉ Saída Listagens Variáveis !_base_1! - !_base_20!
    for /L %%i in (1 1 !_cnt!)do set "_b=00%%~i" && call echoBase "!_b:~-2!": !_base_%%~i!
Base 01: Audio Endpoint Builder
Base 02: Audio
Base 03: Event Log
Base 04: Font Cache Service
Base 05: Presentation Foundation Font Cache 3.0.0.0
Base 06: Phone IP over USB Transport (IpOverUsbSvc)
Base 07: License Manager Service
Base 08: Defender Firewall
Base 09: Security Service
Base 10: Image Acquisition (WIA)
Base 11: Biometric Service
Base 12: Connection Manager
Base 13: Connect Now - Config Registrar
Base 14: Defender Antivirus Network Inspection Service
Base 15: Defender Antivirus Service
Base 16: Management Instrumentation
Base 17: Push Notifications System Service
Base 18: Search
Base 19: Update
Base 20: Push Notifications User Service_6a4f9

EDIT /*



  • Obtenha sua substring na 1ª ocorrência do seu looping:
@echo off

for /f "tokens=* delims= " %%s in ('sc query ^| find /i "OracleService"') do (
     
     set "_var=%%~s"
     set "_3d=%_var:~-3%"
      
     goto :LABEL
    
   )

:LABEL
echo%_var%
echoNome da Base: %_3d%
  • Versão compacta e sem uso de "layout didático" no código:
@echo off && setLocal EnableDelayedExpansion

for /f tokens^=* %%s in ('
%__APPDIR__%sc.exe query^|find/i "OracleService"
')do set "_var=%%~s" && call set "_3d=!_var:~-3!" & goto :^v

:^v
echo%_var% & echoNome da Base: %_3d% & endlocal & goto :EOF
  • Para obter no nome do serviço o nome da base e pegar os 3 últimos caráteres
    já salvando essa string numa variável, apenas utilize :~-3
set !"_var=%%~s!"
set !"_3d=%_var:~-3%!"
    
rem :: ou...
')do set "_var=%%~s" & call set "_3d=!_var:~-3!"  ⁄⁄ para uso na mesma linha⁄layout compacto
  • Para retornar somente a 1ª ocorrência no looping, crie uma fuga usando um
    :label para sair desse looping na 1ª execução já salvando sua substring
set !"_var=%%~s!"
set !"_3d=%_var:~-3%!"
    
goto :LABEL
    
rem :: ou...
')do set "_var=%%~s" & call set "_3d=!_var:~-3
set "_var=%%~s" & call set "_3d=!_var:~-3!" & goto :label  ⁄⁄ para uso na mesma linha⁄layout compacto

Obs.: 3 |find/i 'OracleService' ⁄⁄ Use 'case-insensitive == /i' no seu 'find'

Só utilize o nome literal quando estiver certeza que a string tem somente ocorrências com esse layout, caso contrário, considere que string possa divergir (contendo somente maiúsculas/minúsculas ou ainda outras variações imprevisíveis) do layout atualmente em uso presumido no seu código



  • Obtenha sua substring na última ocorrência do seu looping:
@echo off && Setlocal EnableDelayedExpansion 

for /f %%i in ('sc query ^| find /i "OracleService" ^| find /v /c ""') do (

     if /i %%~i gtr 2 (
      
         call set /a "_x=%%i-1"
         
         for /f "tokens=* delims= " %%s in ('sc query ^| find /i "OracleService" ^| more /s +!_x!') do (
          
             set "_var=%%~s"
             call set "_3d=!_var:~-3!"
         
            )
        
        ) else if %%~i equ 1 (
        
             for /f tokens^=* %%s in ('sc query ^| find /i "OracleService"') do (
             
                 set "_var=%%~s"
                 call set "_3d=!_var:~-3!"
                 
                )
                 
            ) else (
                
                 echoServico OracleService nao foi encontrado em execucao
                 timeout /t -1
                 
                 goto :EOF
                    
            )
        )
    )
    
echo%_var% && echo%_3d% & endlocal  & goto :EOF
  • Versão compacta e sem o uso de "layout didático" no código:
@echo off && setLocal EnableDelayedExpansion 
    
for /f %%i in ('%__APPDIR__%sc.exe query^|find/i "OracleService"^|find/v /c ""')do if %%~i gtr 2 (
  call set /a "_x=%%i-1" && for /f tokens^=* %%s in ('%__APPDIR__%sc.exe query^|find/i "OracleService"^|%__APPDIR__%more.com /s +!_x!
 ')do set "_var=%%~s" && call set "_3d=!_var:~-3!" ) else if %%~i equ 1 (for /f tokens^=* %%s in ('%__APPDIR__%sc.exe query^|find/i "OracleService" 
 ')do set "_var=%%~s" && call set "_3d=!_var:~-3!" ) else echoServico OracleService nao encontrado em execucao^^!! & %__APPDIR__%timeout.exe -1 & endlocal & goto :EOF
    
echo%_var% && echoNome da base: %_3d% & endlocal & goto :EOF


  • Para obter a última ocorrência será necessário fazer a contagem e operar no total (ocorrências) -1, onde o que vai importar saber é:
Se Total ≥ 2 ⁄⁄ pular na listagem Total - 1
Se Total = 1 ⁄⁄ apenas usar mais ações não são necessárias
Se Total = 0 ⁄⁄ informar serviço não encontrado

Obs.: 4 Provavelmente não precise de nada nas informações adicionais do state^=all.

for /f %%i in ('sc query state^=all^| find /i "OracleService" ^| find /v /c ""') do ... 



Answered by Io-ol on November 8, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP