Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Как из for получить значение из одной строки смещаясь на 1 при каждом проходе (http://forum.oszone.net/showthread.php?t=214156)

Voodooman 27-08-2011 14:57 1740326

Как из for получить значение из одной строки смещаясь на 1 при каждом проходе
 
Условия:
Имею 2 "рафинированных" файла со списками, в первом файле по имени name.txt в каждой строчке имеются строки с названиями, во втором файле имеются айди соответсвующие именам именам в первом файле, то есть айди из первой строки соответствует имени из первой строки, айди из 555 строки id.txt соответствует имени из 555 строки в id.
Требуется:
Получить в каждом проходе 2 соответствующие друг друг переменных из одной и той же строчки в двух разных файлах, при следующем проходе перезаписать их новыми переменными со следующей строки

Код:
PHP код:

setlocal enabledelayedexpansion
ECHO on
SET N
=0
FOR /"usebackq tokens=* delims=" %%A IN (name.txt) DO (
    FOR /
"usebackq skip=%N% tokens=* delims=" %%B IN (id.txt) DO (
        
SET /a N=!N!+1
        SET GameName
=%%A
        SET GameId
=%%B
    
)
    ECHO !
GameName!=!GameId!
)
pause 

Проблема:
Первый For получающий имя без всяких проблем каждый цикл переходит к новой строчке пока не достигнет конца файла, с каждым новым проходом я получаю нужно мне имя файла.
Но второй цикл For, заключенный внутри первого, при выходе из цикла и возврате в предыдущий из которого уже выводится эхо, всегда дает мне айди из последней строки таким образом разным именам всегда присваивается 1 и тот же айди.
Я пробовал перенести эхо внутрь второго цикла, но при этом получался противоположный эффект - я получал 1 и то же имя с разными айди.
Я попробовал добавить skip=N и ввел простой счетчик прохода N=N+1 и пытаюсь его значение подставить в качестве значения пропускаемых строк, по логике я на самом деле должен получить такой результат как и до этого (это я уже сообразил после добавления, ведь даже если я начиная с другой строки, все равно цикл закончится последней :D ), но по странной причине ошибка в синтаксисе.
Ну в общем не знаю, как заставить внутренний цикл читать одну заданную номерную строчку вместо всех и завершаться. Я где то видел что внутри IN указывали примерно вот таким способом ([1] [555]) номер нужной строчки, но как это совместить с именем файла и каков правильный синтаксис еще и с подстановкой переменной N?

П.С. - Как я понял find и findstr в моем случае не получится использовать, так как изначально неизвестно что искать, кроме номера строчки. В общем очень нуждаюсь в помощи, залип с такой простой вещью, а документация что в винде что в нете слишком куцая чтобы найти решение.

Iska 27-08-2011 15:52 1740369

Voodooman, для правильного понимания не хватает примеров всех четырёх файлов: что есть и что нужно получить в итоге.

Voodooman 27-08-2011 16:02 1740376

4 файла???
2 же))
Я вроде бы доступно все объяснил, не хочу показаться грубым, но чуть выше все разжевано на пальцах так, что можно обойтись и без примеров и все правильно понять.
Но ладно, попробую еще более доступно объяснить:

name.txt
Код:

name 1
name 2
another name
one more name
etc

id.txt
Код:

125162
446
68568
434637
3535

Что я получаю:
Код:

name 1=3535
name 2=3535
another name=3535
one more name=3535
etc=3535

Что нужно получить:
Код:

name 1=125162
name 2=446
another name=68568
one more name=434637
etc=3535


Foreigner 27-08-2011 16:56 1740416

Voodooman,
Цитата:

Что нужно получить:
Код:

name 1=125162
name 2=446
another name=68568
one more name=434637
etc=3535
При условии, что все файлы без пустых строк
Код:

@echo off
setlocal

<id.txt set /p "firstid="
<names.txt set /p "firstname="

echo %firstname%=%firstid%
set "skip=0"
for /f %%i in (id.txt) do set /a cnt+=1

:loop
if %skip% equ %cnt% goto:eof
set /a skip+=1

for /f "skip=%skip% tokens=*" %%i in (id.txt) do (
   
    for /f "skip=%skip% tokens=*" %%j in (names.txt) do echo %%j=%%i && goto:loop

)


Voodooman 27-08-2011 18:13 1740472

Я уже справился с задачей сам - решил совсем не использовать дампы со списком имен и айди, так как не нашел нормального способа заставить внутренний цикл for обработать одну строчку и завершиться, вместо прохода по всем строчкам, по этому использовал чтение одного ini файла соответсвующего имени напрямую, так хоть во внутреннем for не появляется десяток лишних циклов:

PHP код:

setlocal enabledelayedexpansion
echo off
call 
:MainFunction
pause
exit

rem предпочитаю делить код на легко читаемые и понимаемые подпрограммыфункции и вызывать при необходимости
:MainFunction
FOR /"tokens=* delims=" %%A IN ('dir *.ini /b /o:gn') DO ( 
    FOR /
"usebackq tokens=3* delims=/" %%B IN ("%%~nA.ini") DO (
        
SET GameName=%%~nA
        SET GameId
=%%B
    
) && SET /a N=!N!+1
    call 
:Debug
)
exit /
b


:Debug
echo !N!=!GameName!=!GameId!
exit /


Но меня все еще интересует как сделать первым методом, должен же быть способ выборочного чтения конкретной строчки.
Foreigner, cкрипт работает, но что это за синтаксис такой страшный?
Можно пояснения как он работает и в чем моя ошибка?

Что делает вот это и зачем оно вообще нужно?
<id.txt set /p "firstid="

Зачем выводить первое эхо, ставить две переменных счетка skip и cnt и еще и сравнивать их? Зачем выпрыгивать из цикла for во внешний loop, неужели нет более простого и лаконичного способа прочитать 1 конкретную строку из for и закончить цикл?
Можно в более удобоваримом виде и с комментариями?

Iska 27-08-2011 18:40 1740486

Цитата:

Цитата Voodooman
4 файла??? 2 же))

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

Вот вам и ответ: я воспринял текст не верно, как два исходных и два — результирующих. А оказалось — три файла. Именно их содержание Вы привели далее.

Видите ли, коллега, приведение примеров позволяет дать наглядный образец и помогает лучше воспринимать формальный текст поставленного задания.

P.S. Можно спросить, например, у Foreigner'а — облегчили ли ему приведённые примеры понимание сути вопроса, или же они лишние?


Цитата:

Цитата Voodooman
Foreigner, cкрипт работает, но что это за синтаксис такой страшный? »

Нормальный синтаксис ;). Я не проверял работоспособность, но выглядит всё вполне цивильно и наглядно.

Цитата:

Цитата Voodooman
Что делает вот это и зачем оно вообще нужно?
Код:

<id.txt set /p "firstid="
»

Первая строка файла «id.txt» считывается в переменную окружения «firstid».

Цитата:

Цитата Voodooman
Но меня все еще интересует как сделать первым методом, должен же быть способ выборочного чтения конкретной строчки. »

Цитата:

Цитата Voodooman
неужели нет более простого и лаконичного способа прочитать 1 конкретную строку из for и закончить цикл? »

В принципе — есть. «more» умеет выводить текст, начиная с указанной строки. Другое дело, что ограничить вывод последующих строк через «more» не представляется возможным, и придётся всё одно отсекать вывод этих последующих строк, например, разбором через FOR и прерыванием цикла разбора на первом шаге. Например, читаем четвёртую строку файла «some.txt»:
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

for /f "delims=" %%i in ('^<"some.txt" more +3') do set sValue=%%i & goto :lBreak
:lBreak

echo %sValue%

endlocal
exit /b 0

Другой возможный способ прерывания цикла описал amel27 здесь.

Foreigner 27-08-2011 19:00 1740495

Цитата:

Что делает вот это и зачем оно вообще нужно?
<id.txt set /p "firstid="
Берет первую строчку из файла. что бы потом можно было ее пропустить ( skip ). Т.к. skip=0 выдаст ошибку.
Цитата:

Зачем выпрыгивать из цикла for во внешний loop, неужели нет более простого и лаконичного способа прочитать 1 конкретную строку из for и закончить цикл?
Здесь же два цикла, по одному для каждого файла. Причем они должны быть одновременными. Я не придумал решения проще, чем прерывать оба цикла после прочтения первых строк в файлах и увеличения кол-ва пропущенных строк при каждой итерации в :loop. А переменные сравниваются для того, что бы не уйти в бесконечный цикл. Можно конечно все загнать в коллекцию переменных, а потом их разименовать:
Код:

@echo off
setlocal enabledelayedexpansion

for /f "tokens=*" %%i in (names.txt) do call:set names "%%i"
set "cnt="
for /f "tokens=*" %%i in (id.txt) do call:set id "%%i"

for /l %%i in (1,1,%cnt%) do echo !names_%%i!=!id_%%i!
goto:eof

:set
set /a cnt+=1
set "%1_%cnt%=%~2"

Просто я по возможности избегаю enabledelayedexpansion при echo-выводе текста.

Iska 27-08-2011 19:06 1740499

Цитата:

Цитата Foreigner
Можно конечно все загнать в коллекцию переменных, а потом их разименовать: »

Кстати, тоже вариант. И, главное — самый быстрый. Лишь бы в ограничения командного процессора на целочисленные переменные число строк уместилось.
Цитата:

Цитата Foreigner
Просто я по возможности избегаю enabledelayedexpansion при echo-выводе текста. »

А почему? Я, напротив — всегда использую.

Foreigner 27-08-2011 19:13 1740502

Цитата:

Цитата Iska
А почему? Я, напротив — всегда использую. »

Да что-то как-то так пошло, чистые батники и так с текстом работают "не слишком", а тут еще придется заботится о "!". Правда это не отменяет "%". Есть конечно универсальные решения, но это усложняет код. Имхо

Voodooman 27-08-2011 19:42 1740522

Ну я тут на самом деле эхой из дебаг функции заменил кучу других функций и значительно скрипт сократил, чтобы не отвлекались на ненужные вещи, в данном случае меня интересуе соответсвие строк двух переменных.

Вот сейчас в своем решении без дампа списка файлово решил добавить по мимо считывания имени из названия ини файла и считывания айди из самого инишника, еще и считывания параметра с именем иконки, но вот беда все та же случилась - for начинает парсить все строки непрерывно и в итоге выдает мне последнюю по выходу из его цикла.
Я бы мог в 3 форе как и во 2 использовать делиметер с бекслешем и токеном, но вот беда еще в том, что количество бекслешей в искомой строке может различаться в некоорых инишника и соответсвенно я не знаю точно сколько токенов отсчитывать от начала строки, может есть способ отсчитывать токены от конца или число симоволов из нужной строчки от конца отсчитать и взять за переменную?

Дело в том что ваши методы джама из for во вне мне не подходят, так как у меня 3 фложенных for и прыжок прервет все 3, я попробовал сделать функцию внутри for b выпрыгнуть лишь за пределы 3го во второй, но увы обломался, похоже cmd не поддерживает таких джампов внутри цикла из более глубокого в менее без прерывания последнего.

В общем мне все еще надо считать одну строку из файла и прервать наследующий for не прерывая родительский или заменить какой то командой которая однозначно умеет читать только одну строку.
Я поверить не могу что МС выдумывая кучу сложных вещей для бат файла не придумали простого способа задать и исполнить лишь одну строку.


Вот как можно прервать один фор после первого или заданного прохода не прерывая второго? Может можно использовать как то skip относительно конца файла? например так skip=3,-3 - не читать первые и последние 3 строчки, а если между ними всего одна, то как раз получается нужный результат.

Iska 27-08-2011 20:53 1740564

Цитата:

Цитата Foreigner
Да что-то как-то так пошло, чистые батники и так с текстом работают "не слишком", а тут еще придется заботится о "!". Правда это не отменяет "%". Есть конечно универсальные решения, но это усложняет код. Имхо »

Foreigner, спасибо, ясно.


Цитата:

Цитата Voodooman
Дело в том что ваши методы джама из for во вне мне не подходят, так как у меня 3 фложенных for »

Voodooman, а может тогда стоит перейти на WSH?

Voodooman 27-08-2011 21:33 1740590

Не, WSH не стоит, я с ним не знаком и тут мне уже принципиально надо заставить бат файл каким то хитрым способом прочить только одну строчку!)) Я не успокоюсь пока не заставлю его это сделать)))

Решил поискать внешние консольные утилиты для упрощения задачи и поставки их в комплекте вместе с готовым батником, наткнулся на эту утилиту для чтения, изменения и удаления параметров из ини файлов через батники http://www.horstmuc.de/wbat32.htm#inifile

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

Но все же нейтив метод предпочительней, я пока от мук избавляю себя этой прогой, но хочу все равно узнать как выйти из фора внутри фора после 1 прохода по заданной строчке и при этом не выходить из верхнего. Должен же быть способ.

Кстати, я забыл, как мне из полученной строки взять и использовать в качестве переменной последние 44 символа без всяких делиметеров и токенов? какие там операторы нужно использовать?

kiripanda 27-08-2011 21:46 1740600

Цитата:

Цитата Foreigner
Просто я по возможности избегаю enabledelayedexpansion при echo-выводе текста. »

Код:

for /l %%j in (1,1,%cnt%) do call echo %%names_%%j%%=%%id_%%j%%

Foreigner 27-08-2011 22:04 1740606

kiripanda, можно и так.

Voodooman 27-08-2011 22:25 1740622

А кто нибудь на мои вопросы здесь ответит?))
еще раз спрошу - как взять значение из указанной строчки и прервать лишь 1 фор после этого чтобы избежать парсинга отсальных строк?

Iska 27-08-2011 23:01 1740647

Цитата:

Цитата Voodooman
Не, WSH не стоит, »

Это как?

«%systemroot%\system32\wscript.exe» наличествует?
Цитата:

Цитата Voodooman
я с ним не знаком и тут мне уже принципиально надо заставить бат файл каким то хитрым способом прочить только одну строчку!)) Я не успокоюсь пока не заставлю его это сделать))) »

Спасибо, Ваша цель понятна.

Цитата:

Цитата Voodooman
А кто нибудь на мои вопросы здесь ответит?)) »

Я даже не понял вопрос:
Цитата:

Цитата Voodooman
как взять значение из указанной строчки и прервать лишь 1 фор после этого чтобы избежать парсинга отсальных строк? »


Voodooman 27-08-2011 23:34 1740668

(флейм удален)

Iska 28-08-2011 01:29 1740724

Цитата:

Цитата Voodooman
давай ты не будешь играть в дурака?
»

Предпочитаю лучше выглядеть дураком и спросить, нежели изображать понимание там, где его у меня нет. Если Вы об этом.

читать дальше »
По поводу Ваших прочих многих слов, не относящихся к сути вопроса, равно тона, коим они высказаны… Не получается у Вас сарказм.

Что ж, продолжайте дискуссию в том же духе — и обрящите. Я же — учту на будущее.

Foreigner 28-08-2011 05:54 1740747

Voodooman,
Штатными средствами, без счетчиков и не зная содержимое строки, этого сделать нельзя. Для парсинга текста написано много утилит -- sed, awk, grep, gsar и т.д.


Время: 05:55.

Время: 05:55.
© OSzone.net 2001-