Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Как из for получить значение из одной строки смещаясь на 1 при каждом проходе

Закрытая тема
Настройки темы
CMD/BAT - Как из for получить значение из одной строки смещаясь на 1 при каждом проходе

Новый участник


Сообщения: 12
Благодарности: 1

Профиль | Отправить PM | Цитировать


Изменения
Автор: Voodooman
Дата: 27-08-2011
Условия:
Имею 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 в моем случае не получится использовать, так как изначально неизвестно что искать, кроме номера строчки. В общем очень нуждаюсь в помощи, залип с такой простой вещью, а документация что в винде что в нете слишком куцая чтобы найти решение.

Отправлено: 14:57, 27-08-2011

 

Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


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

Отправлено: 15:52, 27-08-2011 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

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


Новый участник


Сообщения: 12
Благодарности: 1

Профиль | Отправить PM | Цитировать


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

Отправлено: 16:02, 27-08-2011 | #3


Ветеран


Сообщения: 1754
Благодарности: 965

Профиль | Цитировать


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

)

Последний раз редактировалось Foreigner, 27-08-2011 в 17:16.


Отправлено: 16:56, 27-08-2011 | #4


Новый участник


Сообщения: 12
Благодарности: 1

Профиль | Отправить PM | Цитировать


Я уже справился с задачей сам - решил совсем не использовать дампы со списком имен и айди, так как не нашел нормального способа заставить внутренний цикл 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 и закончить цикл?
Можно в более удобоваримом виде и с комментариями?

Отправлено: 18:13, 27-08-2011 | #5


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Цитата 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 здесь.

Последний раз редактировалось Iska, 27-08-2011 в 19:01.

Это сообщение посчитали полезным следующие участники:

Отправлено: 18:40, 27-08-2011 | #6


Ветеран


Сообщения: 1754
Благодарности: 965

Профиль | Цитировать


Цитата:
Что делает вот это и зачем оно вообще нужно?
<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-выводе текста.
Это сообщение посчитали полезным следующие участники:

Отправлено: 19:00, 27-08-2011 | #7


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Цитата Foreigner:
Можно конечно все загнать в коллекцию переменных, а потом их разименовать: »
Кстати, тоже вариант. И, главное — самый быстрый. Лишь бы в ограничения командного процессора на целочисленные переменные число строк уместилось.
Цитата Foreigner:
Просто я по возможности избегаю enabledelayedexpansion при echo-выводе текста. »
А почему? Я, напротив — всегда использую.

Отправлено: 19:06, 27-08-2011 | #8


Ветеран


Сообщения: 1754
Благодарности: 965

Профиль | Цитировать


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

Отправлено: 19:13, 27-08-2011 | #9


Новый участник


Сообщения: 12
Благодарности: 1

Профиль | Отправить PM | Цитировать


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

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

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

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


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

Отправлено: 19:42, 27-08-2011 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Как из for получить значение из одной строки смещаясь на 1 при каждом проходе

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - [решено] Как получить значение параметра из реестра, добавить значение в текстовый файл etc.? Dark Ange1 Скриптовые языки администрирования Windows 28 22-06-2022 14:37
CMD/BAT - Как получить значение искомой подстроки в строке? Loki3D Скриптовые языки администрирования Windows 11 24-02-2018 08:37
Доступ - Как получить права на файл или реестр из командной строки и вернуть всё как было hb860 Microsoft Windows 7 9 25-02-2013 14:03
Как определить кодировку строки передаваемой как значение параметра OLE-серверу Excel RUVATA AutoIt 12 13-12-2010 23:22
Как получить значение CPU и VM. Желательно на С++ Lenycik Программирование и базы данных 3 16-05-2007 12:07




 
Переход