Question doser par lots à travers une chaîne délimitée


J'ai une liste délimitée d'IP que je souhaite traiter individuellement. La longueur de la liste est inconnue à l'avance. Comment diviser et traiter chaque élément de la liste?

@echo off
set servers=127.0.0.1,192.168.0.1,10.100.0.1

FOR /f "tokens=* delims=," %%a IN ("%servers%") DO call :sub %%a

:sub
    echo In subroutine
    echo %1
exit /b

Les sorties:

In subroutine
127.0.0.1
In subroutine
ECHO is off.

Mettre à jour: En utilisant la réponse de Franci comme référence, voici la solution:

@echo off
set servers=127.0.0.1,192.168.0.1,10.100.0.1

call :parse "%servers%"
goto :end


:parse
setlocal
set list=%1
set list=%list:"=%
FOR /f "tokens=1* delims=," %%a IN ("%list%") DO (
  if not "%%a" == "" call :sub %%a
  if not "%%b" == "" call :parse "%%b"
)
endlocal
exit /b

:sub
setlocal
echo In subroutine
echo %1
endlocal
exit /b

:end

Les sorties:

In subroutine
127.0.0.1
In subroutine
192.168.0.1
In subroutine
10.100.0.1

36
2018-03-26 16:32


origine


Réponses:


Mettre à jour: Si le nombre d'éléments de la liste n'est pas connu, il est toujours possible d'analyser tous les éléments avec une simple récursivité sur la tête de la liste. (J'ai changé les adresses IP en nombres simples pour simplifier la liste)

Finalement, la classe Lisp que j'ai prise il y a 18 ans a payé ...

@echo off
setlocal

set servers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24

echo %servers%

call :parse "%servers%"

goto :eos

:parse

set list=%1
set list=%list:"=%

FOR /f "tokens=1* delims=," %%a IN ("%list%") DO (
  if not "%%a" == "" call :sub %%a
  if not "%%b" == "" call :parse "%%b"
)

goto :eos

:sub

echo %1

goto :eos

:eos
endlocal

27
2018-03-26 16:42



La commande for gère un certain nombre de délimiteurs par défaut. Dans ce cas, vous pouvez faire

@echo off

set servers=127.0.0.1,192.168.0.1,10.100.0.1

for %%i in (%servers%) do (
  echo %%i
)

Si vous rencontrez un délimiteur qui n'est pas pris en charge en mode natif, vous pouvez effectuer un remplacement pour préparer d'abord la chaîne afin qu'elle soit au bon format.

@echo off

set servers=127.0.0.1@192.168.0.1@10.100.0.1
set servers=%servers:@=,%

for %%i in (%servers%) do (
  echo %%i
)

L'utilisation d'appels récursifs a la possibilité de manquer d'espace une fois que vous dépassez un certain nombre d'éléments de la liste. Le test de récursivité semble également ralentir un peu.


91
2017-11-10 20:50



La difficulté est que la commande for est destinée à fonctionner sur des chaînes de texte multilignes que vous trouverez généralement dans des fichiers. La meilleure solution à ce problème est de modifier votre chaîne pour qu'elle soit multiligne.

rem You need to enable delayed expansion, otherwise the new line will interfere
rem with the for command.
setlocal ENABLEDELAYEDEXPANSION
rem The following three lines escape a new line and put it in a variable for
rem later.
rem The empty lines are important!
set newline=^


set list=jim alf fred
for /F %%i in ("%list: =!newline!%") do (echo item is %%i)

Cette boucle finale va parcourir les éléments de la variable séparée par des espaces. Il le fait en remplaçant l'espace dans la variable de liste par de nouvelles lignes, puis en effectuant la boucle normale.


6
2018-03-08 22:48



Je ne peux pas croire que c'est si compliqué! On dirait que tout le monde voudrait diviser une chaîne fréquemment sans savoir combien de jetons il contient et sans l’analyser par des lignes. En règle générale, il semble que les gens écrivent dans un fichier, puis le parcourent ou utilisent une méthode multi-sous comme celle-ci. Quel bordel!

Voici ma solution Il est plus facile de suivre et de travailler en ligne, c’est-à-dire sans sous-routine. Il est agréable de créer une liste de noms de fichiers ou autre, puis de les parcourir sans avoir à leur écrire dans un fichier temporaire, de s'assurer qu'il n'y a pas de collision d'écriture, de supprimer le fichier temporaire, etc. une valeur d'un sous-marin comme si c'était une fonction - je ne pense pas que vous puissiez. Donc, vous devriez continuer à écrire 2 sous-marins avec les autres réponses que je vois ici chaque fois que vous vouliez faire quelque chose comme ça - un qui alimente l'autre. Ma méthode vous permet de créer facilement des listes et de les parcourir autant de fois que vous le souhaitez tout au long du script.

setlocal enableextensions enabledelayedexpansion

set SomeList=
set SomeList=!SomeList!a;
set SomeList=!SomeList!b;
set SomeList=!SomeList!c;
set SomeList=!SomeList!d;
set SomeList=!SomeList!e;
set SomeList=!SomeList!f;
set SomeList=!SomeList!g;

set List=!SomeList!
:ProcessList
FOR /f "tokens=1* delims=;" %%a IN ("!List!") DO ( 
  if "%%a" NEQ "" ( 
      echo %%a
  )
  if "%%b" NEQ "" (
      set List=%%b
      goto :ProcessList
  )
)

Sortie:

a
b
c
d
e
f
g

Évidemment, vous pouvez simplement échanger l’écho avec quelque chose d’utile.


4
2018-01-20 20:31



Ceci est une généralisation de la solution de Franci, de sorte que vous pouvez effectuer n'importe quel travail sur chaque élément de votre liste, sans avoir des copies du code d'itération de la liste.

: list_iter
    rem Utilisation: appel: list_iter: do_sub_for_each_item "CSV d'éléments"
    set foo =% 1
    set list =% ~ 2
    pour / f "jetons = 1 * delims =," %% i in ("% list%") fait (
        appelez% foo% %% i
        sinon "%% j" == "" (appel: list_iter% foo% "%% j")
    )
    sortie / b

Par exemple, vous pouvez l'appeler par:

call: list_iter: my_foo "un, deux, trois"
appel: list_iter: my_bar "soleil, caca, wee"

3
2017-08-18 05:24



Oui, je sais que c'est un sujet très ancien, mais j'ai récemment découvert et intéressant le truc qui peut effectuer la séparation demandée d'une manière beaucoup plus simple. C'est ici:

set n=1
set "server[!n!]=%servers:,=" & set /A n+=1 & set "server[!n!]=%"

Ces deux lignes divisent le servers string dans le server  tableau et également définir n variable avec le nombre d'éléments créés. De cette façon, il vous suffit d'utiliser un for /L commande de 1 à %n% traiter tous les éléments. Ici c'est le code complet:

@echo off
setlocal EnableDelayedExpansion

set servers=127.0.0.1,192.168.0.1,10.100.0.1

set n=1
set "server[!n!]=%servers:,=" & set /A n+=1 & set "server[!n!]=%"

for /L %%i in (1,1,%n%) do echo Process server: !server[%%i]!

Cette méthode n'est pas plus simple et plus rapide que toute autre méthode basée sur for commande, mais elle permet aussi d’utiliser directement une chaîne de caractères multiples comme délimiteur.

Vous pouvez lire plus de détails sur la méthode de fractionnement à ce post.


1
2017-10-12 22:42



Si PowerShell est disponible, vous pouvez:

C:>set servers=127.0.0.1,192.168.0.1,10.100.0.1
C:>powershell -NoProfile -Command "('%servers%').Split(',')"
127.0.0.1
192.168.0.1
10.100.0.1

Une autre utilisation pour afficher une variable PATH lisible.

@powershell -NoProfile -Command "($Env:PATH).Split(';')"

ou

powershell -NoProfile -Command "$Env:PATH -split ';'"

0
2017-12-28 02:14