Перечисление границ оператора FOR / F - PullRequest
1 голос
/ 07 февраля 2012

У меня есть оператор FOR / F, в котором я хочу перечислить разделы, которые команда анализирует. Например:

FOR /F "delims=," %%A IN ("This,is,a,comma,delimited,sentence") DO (
    some command to enumerate delims
)
:OUT

Я хочу, чтобы он учитывал каждый разделенный элемент в этом предложении. В этом случае он вывел бы 6

РЕДАКТИРОВАТЬ: Я знаю, что долгий путь будет проверять каждый из них ... но я пытаюсь избежать этого метода:

IF %%A == [] SET enum=0 && GOTO:OUT
IF %%B == [] SET enum=1 && GOTO:OUT

и т.д.

Ответы [ 3 ]

3 голосов
/ 08 февраля 2012

Существует способ прямого перечисления элементов в команде FOR / F "delims = ...".
Вам нужно всего лишь вставить несколько строк в строку.

setlocal EnableDelayedExpansion
set LF=^


rem ** Two empty lines are required

set count=0
FOR /F "tokens=* delims=" %%a in ("item1!LF!item2!LF!item3") DO (
  set /a count+=1
  echo !count!: "%%a"
)
echo(
set "CSV=This,is,a,comma,delimited,sentence"
echo Or with comma separeted text: !CSV!
for %%L in ("!LF!") do set "CSV=!CSV:,=%%~L!"
set count=0
FOR /F "tokens=* delims=" %%a in ("!CSV!") DO (
  set /a count+=1
  echo !count!: "%%a"
)
3 голосов
/ 08 февраля 2012

НЕТ способа напрямую перечислять элементы в команде FOR / F "delims = ...".Обычный способ сделать это - через цикл, который считает один элемент, исключает его из предложения и повторяет, пока был подсчитанный элемент.

Однако, в зависимости от конкретного разделителя и остальных символов в предложенииВы можете использовать команду FOR (без опции / F), которая будет ПОВТОРЯТЬ свой код для каждого элемента, разделенного СТАНДАРТНЫМИ РАЗДЕЛИТЕЛЯМИ ПАРТИИ, которые являются запятой, точкой с запятой и знаком равенства, кроме пробелов.В вашем конкретном примере:

SET ENUM=0
FOR %%A IN (This,is,a,comma,delimited,sentence) DO SET /A ENUM+=1

непосредственно подсчитайте количество элементов, разделенных запятыми.Если разделителем является символ, отличный от запятой, точки с запятой или знака равенства, возможное решение состоит из трех шагов:

1- Replace spaces, comma, semicolon and equal-sign for another know character(s).
2- Replace the delimiter for any Batch standard delimiter (space, comma, etc).
3- Use a simple FOR to directly enumerate the items.
2 голосов
/ 08 февраля 2012

Предложение Аасини использовать простое FOR вместо FOR / F - хорошее решение, если только строка не может содержать подстановочные знаки * или ?. Символ ? может быть защищен поиском и заменой, но эффективного способа замены * в пакете не существует.

Если вы столкнулись с проблемой подстановочных знаков, вы можете вернуться к использованию FOR / F в цикле для разбора одного слова за раз. Большинство людей используют GOTO для выполнения цикла, потому что у вас нет возможности узнать, сколько слов вы найдете. Но GOTO относительно медленный. Вы можете добиться значительного прироста производительности, используя внешний цикл FOR (не FOR / L) с произвольно большим количеством элементов. Внутри тела вы можете выйти из цикла с GOTO, когда больше нет слов. Если цикл проваливается без исчерпания слов, вы можете использовать GOTO для перезапуска цикла. Внешний цикл из 100 элементов будет выполнять только 1 GOTO на 100 проанализированных слов.

@echo off
setlocal enableDelayedExpansion
set "str=This,is,a,comma,delimited,sentence"
set "L10=1 2 3 4 5 6 7 8 9 0"
:loop - The outer FOR loop can handle 100 words before a single GOTO is needed
for %%. in (%L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10% %L10%) do (
  for /f "tokens=1* delims=," %%A in ("!str!") do (
    echo %%A
    if "%%B" == "" goto :break
    set "str=%%B"
  )
)
goto :loop
:break

Как и во всех циклах FOR, вы должны беспокоиться о повреждении ! и ^, если включено отложенное расширение при раскрытии переменной %% A.

FOR / L не следует использовать для внешнего цикла, поскольку FOR / L всегда заканчивает подсчет всех итераций, даже если вы используете GOTO внутри тела.

...