[CMD] Поиск текста в файле и замена на другой

alex_diablo

Постоянный участник
Сообщения
144
Реакции
9
Доброго времени суток!
появилась такая вот задачка:

имеем два текстовых файла:

1.txt

Код:
HJ3DZ72
HJ37H92
4M6TV22
5SQ3F5J
B9L9CC2

2.txt

Код:
MSK-AIVANOV
MSK-BPETROV
MSK-VSIDOROV
MSK-TANISIN
MSK-KFROLOVA

в каждом файле примерно 110-120 строк. каждой строке 1 файла соответствует своя строка во втором файле.

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

CMD/BATCH:
wmic bios get serialnumber

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

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

CMD/BATCH:
for /f "skip=1" %%i in ('"wmic bios get serialnumber"') do echo a=%%i

вот так не выходит.

---- Automatically Merged Double Post ----

CMD/BATCH:
SetLocal EnableExtensions

For /F %%s in ('wmic bios get serialnumber') do set var=%%s
echo %var%

и так тоже.

вот что выводится в результате:
CMD/BATCH:
P:\>SetLocal EnableExtensions

P:\>For /F %s in ('wmic bios get serialnumber') do set var=%s

P:\>set var=SerialNumber

P:\>set var=1WQ3F5J

:\>set var=

P:\>echo
Режим вывода команд на экран (ECHO) включен.

P:\>pause
Для продолжения нажмите любую клавишу . . .

P:\>SetLocal EnableExtensions
P:\>For /F %s in ('wmic bios get serialnumber') do set var=%s
P:\>set var=SerialNumber
P:\>set var=1WQ3F5J
:\>set var=
P:\>echo
Режим вывода команд на экран (ECHO) включен.
P:\>pause
Для продолжения нажмите любую клавишу . . .
 
Последнее редактирование модератором:
с первой частью задачи вроде разобрался.
выглядит так:

CMD/BATCH:
FOR /F "tokens=2 delims='='" %%A in ('wmic Bios Get SerialNumber /value') do SET serialnumber=%%A
echo %serialnumber%

теперь бы решить остальные задачи...
 
Последнее редактирование модератором:
alex_diablo, уверены, что это надёжный способ?
На моей МП (да и на многих других) wmic bios get serialnumber выдаёт:
Код:
SerialNumber
To Be Filled By O.E.M.

с первой частью задачи вроде разобрался.
Да, почти так. Там у wmic ещё лишний знак переноса строки, так что нужно с find:
CMD/BATCH:
For /F "tokens=1* delims==" %%a in ('wmic bios get serialnumber /value ^|find "="') do set serialnumber=%%b
 
alex_diablo, уверены, что это надёжный способ?
На моей МП (да и на многих других) wmic bios get serialnumber выдаёт:
Код:
SerialNumber
To Be Filled By O.E.M.


Да, почти так. Там у wmic ещё лишний знак переноса строки, так что нужно с find:
CMD/BATCH:
For /F "tokens=1* delims==" %%a in ('wmic bios get serialnumber /value ^|find "="') do set serialnumber=%%b

ну вот даже с переносом вроде сработало норм.

а по поводу способа - почти все компы в компании - DELL. у них у всех прописан уникальный код.
поэтому с этим проблем как раз таки и нет, это скорее - единственный способ правильно идентифицировать его.
что же касается остальных - (не ДЕЛЛ) , то их крайне мало. ну еще можно теоретически делать по маку сетевухи, но что делать, если
сетевух несколько, а в таблице, выгруженной из базы компов, он один?

ну и по второму вопросу... не поможете?

может быть тогда сделать.... в одном файле все и разделить каким-нибудь разделителем... например пробелом или точкой...
типа:
Код:
HJ3DZ72.MSK-AFROLOV.50:E5:49:4A:61:54

и тогда подставлять имя по маку исходя из работы команды ipconfig ?

но тут еще нюанс... как быть, если в системе несколько сетевых адаптеров?
 
но тут еще нюанс... как быть, если в системе несколько сетевых адаптеров?
Например, брать МАК адаптера, отмеченного как "Основной", убрав виртуальные (типа VMWare / VBox), можно с фильтрацией по подсети IP (предпоследний октет)
Или взять серийный номер тома (команда vol) или жесткого диска (см. пост), с которого запущена ОС.
Можно ещё взять, но только как часть ID, инфу из SMBIOS и CPUID, но там мало чего уникального и два одинаковых процессора/BIOS будут выдавать идентичные данные (+ это не на Batch).

ну и по второму вопросу... не поможете?
CMD/BATCH:
@echo off
SetLocal EnableExtensions

set SNFile=1.txt
set IDFile=2.txt

For /F "tokens=1* delims==" %%a in ('wmic bios get serialnumber /value ^|find "="') do set serialnumber=%%b
set n=0& set "Found="
For /F "UseBackQ delims=" %%a in ("%SNFile%") do set /a n+=1& if "%serialnumber%"=="%%a" (set Found=true& goto ext)
:ext
if not Defined Found (echo NOT Found!& pause & exit /b)
For /F "tokens=1* delims=]" %%a in ('type "%IDFile%" ^| find /n /v "" ^| findstr /RC:"^\[%n%\]"') do set ID=%%b

echo Line=%n%
echo SN="%serialnumber%"
echo ID="%ID%"

pause
 
Последнее редактирование:
Например, брать МАК адаптера, отмеченного как "Основной", убрав виртуальные (типа VMWare / VBox), можно с фильтрацией по подсети IP (предпоследний октет)
Или взять серийный номер тома (команда vol) или жесткого диска (см. пост), с которого запущена ОС.
Можно ещё взять, но только как часть ID, инфу из SMBIOS и CPUID, но там мало чего уникального и два одинаковых процессора/BIOS будут выдавать идентичные данные (+ это не на Batch).


CMD/BATCH:
@echo off
SetLocal EnableExtensions

set SNFile=1.txt
set IDFile=2.txt

For /F "tokens=1* delims==" %%a in ('wmic bios get serialnumber /value ^|find "="') do set serialnumber=%%b
set n=0& set "Found="
For /F "UseBackQ delims=" %%a in ("%SNFile%") do set /a n+=1& if "%serialnumber%"=="%%a" (set Found=true& goto ext)
:ext
if not Defined Found (echo NOT Found!& pause & exit /b)
For /F "tokens=1* delims=]" %%a in ('type "%IDFile%" ^| find /n /v "" ^| findstr /RC:"^\[%n%\]"') do set ID=%%b

echo Line=%n%
echo SN="%serialnumber%"
echo ID="%ID%"

pause

класс! а нельзя ли из экселевской таблицы такое сделать?
 
Формат таблиц именно XLS / не CSV ?
Для XLS нужно писать на другом языке, из интерпретируемых, встроенных в ОС, например, VBScript / JScript или PowerShell.
 
Формат таблиц именно XLS / не CSV ?
Для XLS нужно писать на другом языке, из интерпретируемых, встроенных в ОС, например, VBScript / JScript или PowerShell.

ну вроде можно табличку и в CSV выгрузить
 
ну вроде можно табличку и в CSV выгрузить

воспользовался вашим способом определения мака:

Код:
@echo off
SetLocal EnableExtensions
(
for /f %%a in ('getmac^|find /i "device"') do echo %%a
)>mac.txt

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

и таки еще не понятно... как фильтровать... чтобы в результат выдавался только один мак - физического адреса.
 
Последнее редактирование:
Брать данные из ipconfig /all
Фильтровать | find и т.д. или findstr, потом бить на токены через For и tokens, delims
только вот в системе используется разделитель тире, а у меня в таблице октеты маков все разделены двоеточиями...
Заменить на нужное в самой переменной.
Замена - на :
CMD/BATCH:
set s=%s:-=:%
 
Последнее редактирование:
Брать данные из ipconfig /all
Фильтровать | find и т.д. или findstr, потом бить на токены через For и tokens, delims

Заменить на нужное в самой переменной.
Замена - на :
CMD/BATCH:
set s=%s:-=:%

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

Код:
HJ3DZ72;MSK-BPETROV;90-2b-34-33-e9-4b;dell_7010
HJ37H92;MSK-AIVANOV;64-00-6a-32-9b-eb;dell_7020
4M6TV22;MSK-VSIDOROV;64-00-6a-67-ed-18;dell_5040
5SQ3F5J;MSK-TANISIN;34-e6-d7-56-09-24;dell_7010
B9L9CC2;MSK-KFROLOVA;64-00-6a-67-f0-2b;dell_E7240

т.е. 4 значения в каждой строке, разделенные точкой-запятой (серийный номер;имя компа;мак-адрес;модель компа)

что нужно в итоге от скрипта:

командой wmic bios get serialnumber получить значение в первой части строки и записать ее в одну переменную,
и в соответствии этому значению, задать остальные три переменные.

помогите пожалуйста.
 
Чем же помочь? Где ваш код?

HJ3DZ72/MSK-BPETROV/90-2b-34-33-e9-4b/dell_7010
HJ37H92/MSK-AIVANOV/64-00-6a-32-9b-eb/dell_7020
4M6TV22/MSK-VSIDOROV/64-00-6a-67-ed-18/dell_5040
1WQ3F5J/MSK-AKOPYLOV/66-02-64-67-f0-2b/dell_E7010
5SQ3F5J/MSK-TANISIN/34-e6-d7-56-09-24/dell_7010
B9L9CC2/MSK-KFROLOVA/64-00-6a-67-f0-2b/dell_E7240

в общем, начало кода такое:

Код:
@echo off
SetLocal EnableExtensions


REM в файле 4 столбца, разделенные косой чертой: серийный номер/имя-компа/мак-адрес/модель
REM данный файл сформирован заранее.
set IDFile=1.txt

REM выдергиваем серийник из биоса
For /F "tokens=1* delims==" %%a in ('wmic bios get serialnumber /value ^|find "="') do set serialnumber=%%b

echo %serialnumber%

что должен делать скрипт:

1. определить серийный номер из биоса
2. найти его соответствие в таблице и записать в переменную
3. в соответствии с серийником и таблицей, нужно в отдельные переменные записать также: имя-компа, мак-адрес и модель

С первым пунктом все понятно, работает.
Далее, я пытаюсь в соответствии с определенным серийником, определить в переменную значение из сооветствующей строчки:

Код:
FOR /F "UseBackQ tokens=2 delims=/" %%a in ('"%~dp01.txt" ^|find / "%serialnumber%"') do set name=%%a
echo %name%

не получается(

помогите пожалуйста написать код, чтобы по найденному серийнику создать еще 3 переменные, соответсвующие имя-компа/мак-адрес/модель
 
не получается(
Зачем лепите своё. Я уже выше давал код, как искать. Он работает.
Вам всего лишь нужно собрать полную строку, т.е. вместо if "%serialnumber%"== подставить переменную, в которой будет заранее записана полностью ваша строка:

Серийный номер вы уже знаете, как получать.

Имя ПК, производитель, модель:
CMD/BATCH:
@echo off
SetLocal EnableExtensions

:: получить производителя ПК и модель
For /f "tokens=1* delims==" %%a in ('wmic csproduct get vendor^, version /value') do (
  if /i "%%a"=="vendor" set "vendor=%%b"
  if /i "%%a"=="version" set "version=%%b"
)
set "Model=%vendor%_%version%"

:: получить имя ПК
For /f "tokens=1* delims==" %%a in ('wmic computersystem get name /value ^|find /i "name"') do set "PCName=%%b"

set model
set PCName

pause

MAC я не знаю, как вам получить, потому что не знаю, какие у вас критерии для фильтрации нужного.
Я предлагал выше по подсети, первым 3-м октетам. Но я не в курсе допустимо ли это для вашей сети, будет ли она менятся, и какие конкретно там у вас цифры.

Соедините всё вместе и подставьте в код поиска.
 
Зачем лепите своё. Я уже выше давал код, как искать. Он работает.
Вам всего лишь нужно собрать полную строку, т.е. вместо if "%serialnumber%"== подставить переменную, в которой будет заранее записана полностью ваша строка:

Серийный номер вы уже знаете, как получать.

Имя ПК, производитель, модель:
CMD/BATCH:
@echo off
SetLocal EnableExtensions

:: получить производителя ПК и модель
For /f "tokens=1* delims==" %%a in ('wmic csproduct get vendor^, version /value') do (
  if /i "%%a"=="vendor" set "vendor=%%b"
  if /i "%%a"=="version" set "version=%%b"
)
set "Model=%vendor%_%version%"

:: получить имя ПК
For /f "tokens=1* delims==" %%a in ('wmic computersystem get name /value ^|find /i "name"') do set "PCName=%%b"

set model
set PCName

pause

MAC я не знаю, как вам получить, потому что не знаю, какие у вас критерии для фильтрации нужного.
Я предлагал выше по подсети, первым 3-м октетам. Но я не в курсе допустимо ли это для вашей сети, будет ли она менятся, и какие конкретно там у вас цифры.

Соедините всё вместе и подставьте в код поиска.

мак получать не нужно, он известен и заранее записан в таблицу. его просто нужно записать в переменную

---- Automatically Merged Double Post ----

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

имя компа, модель, мак-адрес

т.е. к примеру, скрипт определил, что серийный номер - 5SQ3F5J

значит в соответствии с таблицей, должны быть определены переменные типа:

name = MSK-TANISIN
mac = 34-e6-d7-56-09-24
model = dell_7010

---- Automatically Merged Double Post ----

т.е. строку 5SQ3F5J/MSK-TANISIN/34-e6-d7-56-09-24/dell_7010 нужно разобрать на соответствующие переменные. надеюсь, правильно объяснил суть.
 
Последнее редактирование:
Понял. Всё в одном файле теперь.

Тогда вот так:
Код:
FOR /F "tokens=1-4 delims=/" %%a in ('type "%~dp01.txt" ^|find /i "%serialnumber%"') do (
  set name=%%b
  set mac=%%c
  set model=%%d
)
 
теперь все работает, спасибо! странно. вроде бы пытался что-то похожее сделать, но не получилось(

upd:

и все-таки нужно немного доработать скрипт и сделать более универсальным:

нужно предусмотреть тот вариант, что серийного номера у компа может не оказаться, вернее, это будет что-то типа О.Е.М и если таких компов будет несколько в базе, то привязаться будет не к чему.
тогда нужно сделать поиск по мак-адресу:

значит добавляем строку поиска мака:

Код:
@for /f %%a in ('getmac^|find /i "device"') do set mac=%%a

помогите пожалуйста видоизменить весь код так, чтобы сначала определялся серийный номер и выполнялся поиск по таблице (как изначально было) и добавить проверку на то, что если соответствие по
серийному номеру в таблице не найдено, тогда определять мак-адрес и сравнивать его с маком из таблицы (в таблице мак-адрес для такого компа будет забит, но серийный номер будет отсутствовать) .
дальше все также. нужно записать в переменную соответствующие этому мак-адресу имя и модель компа.
 
вроде сделал:
Bash:
@echo off
SetLocal EnableExtensions

For /F "tokens=1* delims==" %%a in ('wmic bios get serialnumber /value ^|find "="') do set servicetag=%%b

@for /f %%a in ('getmac^|find /i "device"') do set mac-id=%%a

FOR /F "tokens=1-4 delims=/" %%a in ('type "%~dp0computers.txt" ^|find /i "%servicetag%"') do (
  set serial=%%a
  set pcname=%%b
  set mac=%%c
  set model=%%d
)

if "%serial%"=="%servicetag%" (goto rename_pc) else (goto stag_not_found)


:stag_not_found

FOR /F "tokens=1-4 delims=/" %%a in ('type "%~dp0computers.txt" ^|find /i "%mac-id%"') do (
  set pcname=%%b
  set mac=%%c
  set model=%%d
)

if "%mac%"=="%mac-id%" (goto rename_pc) else (goto exit)


:rename_pc

ping mail.ru -n 10

wmic computersystem where name="%computername%" rename "%pcname%"

ping google.com -n 10

:exit

exit

выглядит наверное не очень красиво, но вроде работает.
 
Назад
Сверху Снизу