2013-06-30 2 views
1

Мне нужен быстрый способ вставить несколько строк структурированных данных в файл летучей мыши Я использовал массив с именем myarray для сканирования и «чтения» моих значений, но он не работает, и я не нахожу «т понять, почему Это мой код:for-loop and delimeters

@echo off 
set myarray[1]=myfield1#myfield2#mysubfield31;mysubfield32#myfield4 
for /f "tokens=1-9 delims=#" %%a in ('echo %myarray[1]%') do (
    echo field1 is %%a 
    echo field2 is %%b 
    echo field3 is %%c 
    echo field4 is %%d 
    for /f "tokens=1-9 delims=;" %%k in ('echo %%c') do (
     echo subfield3 is %%k 
     echo subfield3 is %%l  
    ) 
) 

выход, как это:

field1 is myfield1 
field2 is myfield2 
field3 is mysubfield31 mysubfield32 
field4 is myfield4 
subfield3 is mysubfield31 mysubfield32 
subfield3 is 

почему я не могу получить просто:

subfield3 is mysubfield31 
subfield3 is mysubfield32 

где находится «;» используется в качестве деминера во втором для?

ответ

5

Это работает:

@echo off 
set myarray[1]=myfield1#myfield2#mysubfield31;mysubfield32#myfield4 
for /f "tokens=1-9 delims=#" %%a in ("%myarray[1]%") do (
    echo field1 is %%a 
    echo field2 is %%b 
    echo field3 is %%c 
    echo field4 is %%d 
    for /f "tokens=1-9 delims=;" %%k in ("%%c") do (
     echo subfield3 is %%k 
     echo subfield3 is %%l  
    ) 
) 
pause 
-1

Это documented behavior, точка с запятой рассматривается как пробел (но не по контуру for, а подголовкой, выполняющей команду echo). Это приводит к замене точки с запятой пробелом, так что echo field3 is %%c производит выход field3 is mysubfield31 mysubfield32. Либо удалите delims=; из внутреннего цикла, поэтому он использует разделители по умолчанию (пробел и табуляцию) или выбирает другой символ разделителя, и ваш скрипт должен работать должным образом. Обратите внимание, однако, что использование разделителей по умолчанию во внутреннем цикле может приводить к нежелательным результатам, когда поля вложенного «массива» содержат пробелы.

Доказательство:

  1. Демонстрация первопричину:

    не
    for /f "tokens=*" %%a in ('echo.a#b;c#d^|find ";"') do echo _%%a_ 
    

    Выход: нет (т.е. нет запятой найдено в вторит строке)

    for /f "tokens=*" %%a in ('echo.a#b;c#d^|find " "') do echo _%%a_ 
    

    Выход: _a#b c#d_

    Очевидно, это относится ко всем delimiter characters (,, ;, =, пробел и табуляция), так как я мог воспроизвести это поведение с каждым из них.

  2. упрощенный сценарий с входной строки a#b;c#d:

    @echo off 
    set "foo=a#b;c#d" 
    for /f "tokens=1-3 delims=#" %%a in ('echo %foo%') do (
        echo field1 is %%a 
        echo field2 is %%b 
        echo field3 is %%c 
        for /f "tokens=1-2 delims=;" %%k in ('echo %%b') do (
        echo subfield3 is %%k 
        echo subfield3 is %%l  
    ) 
    ) 
    

    Выход:

    field1 is a 
    field2 is b c 
    field3 is d 
    subfield3 is b c 
    subfield3 is

    Примечание пространство между b и c в 2 й и 4 го линии выхода ,

  3. же сценарий, как 2., но с delims=; удаляют из внутреннего цикла:

    @echo off 
    set "foo=a#b;c#d" 
    for /f "tokens=1-3 delims=#" %%a in ('echo %foo%') do (
        echo field1 is %%a 
        echo field2 is %%b 
        echo field3 is %%c 
        for /f "tokens=1-2" %%k in ('echo %%b') do (
        echo subfield3 is %%k 
        echo subfield3 is %%l  
    ) 
    ) 
    

    Выход:

    field1 is a 
    field2 is b c 
    field3 is d 
    subfield3 is b 
    subfield3 is c

    Обратите внимание, что вложенная "массив" b;c (с переменной %foo%) теперь обрабатывается на правильный вывод (строки 4 и 5).Это потому, что пробелы и вкладки являются разделителями по умолчанию в циклах for /f.

  4. же сценарий, как 2., но с использованием + в качестве разделителя для вложенного "массива":

    @echo off 
    set "foo=a#b+c#d" 
    for /f "tokens=1-3 delims=#" %%a in ('echo %foo%') do (
        echo field1 is %%a 
        echo field2 is %%b 
        echo field3 is %%c 
        for /f "tokens=1-2 delims=+" %%k in ('echo %%b') do (
        echo subfield3 is %%k 
        echo subfield3 is %%l  
    ) 
    ) 
    

    Выход:

    field1 is a 
    field2 is b+c 
    field3 is d 
    subfield3 is b 
    subfield3 is c

    Обратите внимание, что 2-й выходной линии нет более длинное содержит фиктивное пространство, и, опять же, вложенный «массив» обрабатывается правильно (строки 4 и 5).


Для полноты: лучшим решением было бы отбросить echo вообще и просто петлю на строку в двойных кавычках, так как foxidrive и Peter Wright предложил, потому что он избегает этой проблемы полностью.

@echo off 
set "foo=a#b;c#d" 
for /f "tokens=1-3 delims=#" %%a in ("%foo%") do (
    echo field1 is %%a 
    echo field2 is %%b 
    echo field3 is %%c 
    for /f "tokens=1-2 delims=;" %%k in ("%%b") do (
    echo subfield3 is %%k 
    echo subfield3 is %%l  
) 
) 

Другое решение, предложенное dbenham, было бы включить замедленное расширение и иметь переменную расширенного во время выполнения:

@echo off 
setlocal EnableDelayedExpansion 
set "foo=a#b;c#d" 
for /f "tokens=1-3 delims=#" %%a in ('echo !foo!') do (
    echo field1 is %%a 
    echo field2 is %%b 
    echo field3 is %%c 
    for /f "tokens=1-2 delims=;" %%k in ('echo %%b') do (
    echo subfield3 is %%k 
    echo subfield3 is %%l  
) 
) 

Еще лучшее решение, однако, было бы бросить партию целиком и переключатель на язык, который фактически поддерживает массивы, например PowerShell.

+2

Неправильно! Точка с запятой рассматривается как разделитель _ в простой (опция no/F) FOR command_. В команде 'FOR/F' разделители - это те, которые помещаются в опцию' delims = ... '. – Aacini

+0

'for/f 'tokens = 1-4 delims =;" % j in ("a; b; c; d") do echo% j% k% l% m' – foxidrive

+1

Вы правы, что в некоторых случаях это разделитель, но вы не правы предлагать удалить его из "delims знак равно как решение. – foxidrive

1
for /f "tokens=1-9 delims=#" %%a in ("%myarray[1]%") do (

может работать чуть лучше ...

+0

Я отредактировал '% array [1]%' name, чтобы люди могли попробовать код и не застрять, царапая голову. Перед тем, как я увидел это, мне потребовалось много исправлений и проклятие случайного поведения CMD в Microsoft. :) – foxidrive