Форум программистов, компьютерный форум, киберфорум
Наши страницы
PowerShell
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
1

Скрипт замены баз в файле ibases.v8i c использованием excel

12.09.2019, 09:14. Просмотров 1114. Ответов 19

Добрый день.
Помогите пожалуйста как сделать замену всех путей баз в файлах ibases.v8i.
Есть сервер, где у кого-то прописаны в файле базы, и эти базы переехали, а поправить нужно у всех, у кого в файле ibases.v8 прописаны старые базы. на новые. При этом новые базы и название старых нужно взять из excel файла.

Я предполагаю действовать следует так
1. Последовательно прочитать все файлы "C:\users\*\appdata...\ibases.v8i"
2. Прочитать базы подлежащие замене из cvs файла, в котором есть поля: "СтарыйСервер","СтароеНазваниеБазы","НовыйСервер","НовоеНазваниеБазы"
2a - учесть ситуацию, когда неизвестно какой указан сервер. То есть может быть что угодно между:
Connect=Srvr="Тутнепонятночто";Ref="base1";
3. Скопировать файлы перед изменением с сохранением структуры у кого производилось изменение (например пользователь user1) - значит в папке backup создать папку с именем User1 и уже туда скопировать.
3. Произвести замену по маске пути на новую базу.
4. Сохранить изменение в исходный файл ibases.v8i

Моё решение промежуточное:
1. Создан файл excel, с последующим сохранением в cvs с указанными значениями выше.
Кликните здесь для просмотра всего текста
Мой код:
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
$replacers = Import-Csv "C:\ps\test1.csv" -Encoding Default -Delimiter ";"
gc C:\ps\ibases.v8i | ForEach-Object {
   $output = $_
   foreach ($r in $replacers) {
     
     $outSrvr='Connect=Srvr="'+$r.Srvr+'";'
     $outRef='Ref="'+$r.Ref+'";'
     $outReplace=$outSrvr+$outRef        
     $output = $output -replace ("^Connect=Srvr=.+[$r.Ref$]??"),($outReplace)
 
   }
   return $output | Out-File C:\ps\ibases11.v8i -Append -Encoding utf8
}


Содержимое файла ibases.v8i Для примера:
Кликните здесь для просмотра всего текста

[База1]
Connect=Srvr="server1";Ref="Base1";
ID=7853661-7598-49778-3gg6-1414451
OrderInList=7859
Folder=/
OrderInTree=458
External=0
App=Auto
WA=1
[База2]
Connect=Srvr="server2";Ref="Base2";
ID=7853661-7598-49778-3gg6-1414551
OrderInList=45889
Folder=/
OrderInTree=78
External=0
ClientConnectionSpeed=Normal
App=Auto
WA=1
Version=8.3
DefaultVersion=8.3.12.1616
[abk _ 2017]
Connect=Srvr="Server3";Ref="Base3";
ID=7853661-7598-49778-3gg6-14148551
OrderInList=4586
Folder=/
OrderInTree=1458
External=0
ClientConnectionSpeed=Normal
App=Auto
WA=1
Version=8.3




Я запутался как сделать регулярное выражение для замены и если выполнять выше код, замена происходит, но например в файле cvs будет последняя база base3, то ВСЕ базы будут замены почему то на base3 и server3
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.09.2019, 09:14
Ответы с готовыми решениями:

Скрипт замены в текстовом файле с файлом замен в цикле
Добрый день всем! Нужно произвести замену в плейлистах .m3u (по сути текстовые файлы). Но так как...

Изменить текст в одном txt-файле с использованием двух других для поиска и замены строк
Здравствуйте, подскажите, пожалуйста как можно заменить текст в одном тхт файле... список того, что...

Редактирование баз в ibases.v8i
Всем привет! Нужна помощь со скриптом который будет дописывать (с проверкой существования) базы...

Скрипт поиска и замены текста в файле
Всем привет! Помогите пожалуйста написать простой скрипт по поиску и замены текста в файле. Есть...

Самый простой и РАБОТАЮЩИЙ скрипт для замены текста в файле
Очень плохо разбираюсь в этих скриптах, надеюсь на понимание....

19
bidstrup
330 / 147 / 22
Регистрация: 11.03.2018
Сообщений: 656
12.09.2019, 09:56 2
А зачем построчный цикл файла ibases.v8i ?
Тебе нужен побазный цикл, по секциям в смысле ( [База1], [База2] )
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 10:03  [ТС] 3
Я ведь не знаю как могут называться все строчки в файле или блоки. Я лишь знаю что есть база, которую нужно править:
Connect=Srvr="server1";Ref="Base1";
А может там будет:
Connect=Srvr="1server1";Ref="Base1";

Сложность ещё заключается в том, что название старых серверов (если нет то неизвестное название) и самих баз нужно указывать в excel.

Если подскажите Ваш вариант, буду признателен любой помощи. Всё равно ведь даже в блоках замена будет через replace
0
bidstrup
330 / 147 / 22
Регистрация: 11.03.2018
Сообщений: 656
12.09.2019, 10:06 4
Иными словами, по-хорошему нужна ещё функция чтения ini-файла в обьект. Такие есть уже готовые.
0
12.09.2019, 10:06
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 10:24  [ТС] 5
Это ведь не ini файл. тут не сделать так:
PowerShell
1
2
3
4
$Ini = Get-Content -Path $FileF | Where-Object { $_ -match 'КаталогПрием=' }
[array]$ContentF=""
$ContentF[0] = $Ini.Split('=')[1]
$ContentF_Change = $ContentF.Replace('%username%','CF\%username%\')
Какие например блоки предлагаете? пример можно адаптированный под мои условия? потому что я не понимаю что именно хотите

Добавлено через 10 минут
У меня важный вопрос как сделать замену ещё т.к. не пойму какую маску сделать для:
1: Connect=Srvr="НЕИЗВЕСТНОЧТО";Ref="Base1";
2: Connect=Srvr="из файла название сервера старого";Ref="Base1";
0
bidstrup
330 / 147 / 22
Регистрация: 11.03.2018
Сообщений: 656
12.09.2019, 10:33 6
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function Parse-IniFile ($file)
{
  $ini = @{}
  switch -regex -file $file
  {
    #Section.
    "^\[(.+)\]$"
    {
      $section = $matches[1].Trim()
      $ini[$section] = @{}
      continue
    }
    #Int.
    "^\s*([^#].+?)\s*=\s*(\d+)\s*$"
    {
      $name,$value = $matches[1..2]
      $ini[$section][$name] = [int]$value
      continue
    }
    #Decimal.
    "^\s*([^#].+?)\s*=\s*(\d+\.\d+)\s*$"
    {
      $name,$value = $matches[1..2]
      $ini[$section][$name] = [decimal]$value
      continue
    }
    #Everything else.
    "^\s*([^#].+?)\s*=\s*(.*)"
    {
      $name,$value = $matches[1..2]
      $ini[$section][$name] = $value.Trim()
    }
  }
  $ini
}
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 10:41  [ТС] 7
Почему то мне кажется это не то направление т.к.
1. Требуется знать название блоков что эта функция выдает на name
2. потом придется пытаться получить содержимое для замены строчки через такое например: ((Parse-IniFile)."что-то").connect.
3. и ведь потом это всё возвращать в исходный файл с другой структурой.
4. Хорошо, получили мы: ту же самую строчку, в которой нужно произвести замену: Connect=Srvr="НЕИЗВЕСТНОЧТО";Ref="Base1";

и снова на том же месте что и я сейчас
0
bidstrup
330 / 147 / 22
Регистрация: 11.03.2018
Сообщений: 656
12.09.2019, 10:58 8
PowerShell
1
2
3
4
5
6
7
8
9
10
11
#USAGE:
 
$ini = Parse-IniFile ./ibases.v8i 
 
foreach ( $section in $ini.keys ) {
   
  ...
   $ini.$section.Connect
  ...
 
}
Добавлено через 14 минут
Я, разумеется, не вникал конкретно, что у тебя там.
Просто методологически, если надо изменить значения в конфиг. файле,
его надо сначала разобрать на обьекты, а затем пройтись по нему с помощью подходящего итератора.
0
KDE777
1600 / 1026 / 403
Регистрация: 22.01.2016
Сообщений: 2,850
12.09.2019, 11:21 9
Цитата Сообщение от dj-12l Посмотреть сообщение
Помогите пожалуйста как сделать замену всех путей баз в файлах ibases.v8i.
Есть сервер, где у кого-то прописаны в файле базы, и эти базы переехали, а поправить нужно у всех, у кого в файле ibases.v8 прописаны старые базы. на новые.
А вы не слышали про такое решение:

1. Всем пользователям в профиль копируется (лучше групповой политикой) файл - 1CEStart.cfg

"$env:USERPROFILE\AppData\Roaming\1C\1CEStart\1CEStart.cfg"

В этом файле пишется одна строчка:

Код
CommonInfoBases=\\dfsroot\share\1C\Bases\ib_common.v8i
2. В файле ib_common.v8i, расположенном на сетевой (лучше dfs) шаре, перечисляете все нужные базы и свойства подключения.

Всё. Теперь изменив список баз в одном сетевом файле, все пользователи при запуске 1С-клиента получат новые настройки.
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 11:41  [ТС] 10
Да, про такой вариант решения я знаю. Только сложность в том что другие пользователи не должны знать у кого какие базы. Баз тысячи! А так получается все будут видеть их.

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

Прошу помочь с вариантом перебрать все файлы у всех пользователей C:\users ...\ibases.v8i на предмет замены из excel файла.
Хотя бы составить маску т.к. уже голова кипит т.к. не отрабатывает replace или заменят всё по последнему значению в файле cvs.

Добавлено через 11 минут
я понимаю что если через dfs, то можно скрывать не нужную информацию у кого нет доступа. Но вопрос в том, что сейчас требуется именно вручную отредактировать файлы, а их очень много. поэтому такой метод решения и остается. И поменять политику выведения списка я не смогу
0
KDE777
1600 / 1026 / 403
Регистрация: 22.01.2016
Сообщений: 2,850
12.09.2019, 11:48 11
Цитата Сообщение от dj-12l Посмотреть сообщение
сложность в том что другие пользователи не должны знать у кого какие базы. Баз тысячи! А так получается все будут видеть их.
Сделайте для разных групп пользователей разные ib_common.v8i (доступные только им). Этим же группам распространяйте соответствующий 1CEStart.cfg.

Цитата Сообщение от dj-12l Посмотреть сообщение
уже голова кипит т.к. не отрабатывает replace
Настройте все один раз нормально и больше не придётся заниматься кипучей деятельностью...

Добавлено через 3 минуты
Цитата Сообщение от dj-12l Посмотреть сообщение
я понимаю что если через dfs, то можно скрывать не нужную информацию у кого нет доступа.
Для этого вовсе не обязательно DFS (ABE) и даже без NTFS ACL можно обойтись, достаточно даже простых share permissions...
0
bidstrup
330 / 147 / 22
Регистрация: 11.03.2018
Сообщений: 656
12.09.2019, 11:52 12
Цитата Сообщение от KDE777 Посмотреть сообщение
Настройте все один раз нормально
Ну ты замахнулся)) Это ж краеугольный камень человеческой жизнедеятельности;
сначала способ <<черезжопу>> оформляется в качестве правила или закона, а затем все последующие поколения занимаются неизбежной кипучей деятельностью.
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 12:00  [ТС] 13
Цитата Сообщение от KDE777 Посмотреть сообщение
Настройте все один раз нормально и больше не придётся заниматься кипучей деятельностью...
Я согласен, что такой вариант хороший!
У нас есть специальный ярлык что отображает нужные базы пользователю и переезды не страшны. Но сейчас нет возможности это сделать, а есть сотни людей у которых нужно заменить базы и прав у меня на групповые политики нет. Поэтому подскажите хотя бы, какую маску использовать для замены? Как гуру регулярных выражений.

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

Если требуется, я сделаю прям полный комплект для примера с cvs
0
KDE777
1600 / 1026 / 403
Регистрация: 22.01.2016
Сообщений: 2,850
12.09.2019, 13:26 14
Цитата Сообщение от dj-12l Посмотреть сообщение
Я запутался как сделать регулярное выражение для замены и если выполнять выше код, замена происходит, но например в файле cvs будет последняя база base3, то ВСЕ базы будут замены почему то на base3 и server3
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$v8i_path = 'C:\Temp\1CEStart'
$csv_list = "C:\Temp\1CEStart\new_1c_bases.csv"
 
$base_list = Import-Csv -Path $csv_list -Delimiter ';' -Encoding Default
 
ForEach ($v8i_file in Get-ChildItem -Path $v8i_path\*.v8i -File)
{
    $config = Get-Content -Path $v8i_file -Encoding UTF8
    
    ForEach ($base in $base_list)
    {
        $Pattern = "^Connect=Srvr=.+;Ref=`"$($base.СтароеНазваниеБазы)`";$"
        $config = $config -replace $Pattern,"Connect=Srvr=`"$($base.НовыйСервер)`";Ref=`"$($base.НовоеНазваниеБазы)`";"
    }
 
    $config | Set-Content -Path $v8i_file -Encoding UTF8
}
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 14:32  [ТС] 15
Цитата Сообщение от KDE777 Посмотреть сообщение
$Pattern = "^Connect=Srvr=.+;Ref=`"$($base.СтароеНазваниеБазы)`";$"
Что требуется указать что если неизвестно старое название?
или в exel написать в ячейке .+?

Добавлено через 10 минут
Возможно ли сделать копию файла именно только где производилась замена или нет? условие что есть что заменить через Match?
0
KDE777
1600 / 1026 / 403
Регистрация: 22.01.2016
Сообщений: 2,850
12.09.2019, 14:34 16
Цитата Сообщение от dj-12l Посмотреть сообщение
Что требуется указать что если неизвестно старое название?
тогда это бессмысленная задача, т.к. под шаблон:

Код
Connect=Srvr="ServerName";Ref=".+";
попадут все подключения.
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 14:44  [ТС] 17
Цитата Сообщение от KDE777 Посмотреть сообщение
тогда это бессмысленная задача, т.к. под шаблон:
Согласен.
Я думал вы сделали еще проверку старого сервера, но как сделали пойдет и хорошо.

Насколько понял, требуется указать $v8i_path = 'C:\users'
и он пройдет по всем папкам пользователей?

2.Возможно ли сделать backup тех файлов v8i, что будут изменяться.
Я подумал может сделать условие $Pattern = "^Connect=Srvr=.+;Ref=`"$($base.СтароеНазваниеБазы)`";$" - Matсh, то тогда если истинно, сделать item-copy, перед заменой. с сохранением структуры оригинального файла - то есть если нашелся файл в c:\users\ivanov\1cstart\v8i То и бэкап сделать в папку указанную в переменной другой c:\backup\users\ivanov - чтобы найти можно было изменения, а то мало ли не такй что пойдет в замене
0
KDE777
1600 / 1026 / 403
Регистрация: 22.01.2016
Сообщений: 2,850
12.09.2019, 15:12 18
Лучший ответ Сообщение было отмечено dj-12l как решение

Решение

Цитата Сообщение от dj-12l Посмотреть сообщение
Насколько понял, требуется указать $v8i_path = 'C:\users'
и он пройдет по всем папкам пользователей?
Нет так показанный выше скрипт не сработает.

Цитата Сообщение от dj-12l Посмотреть сообщение
Возможно ли сделать backup тех файлов v8i, что будут изменяться.
Конечно возможно, в чём именно возникли сложности?

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$users_path = 'C:\Users'
$csv_list   = '\\server\share\new_1c_bases.csv'
 
$base_list = Import-Csv -Path $csv_list -Delimiter ';' -Encoding Default
 
ForEach ($v8i_file in Get-ChildItem -Path $users_path -Directory | Get-ChildItem -Path {"$($_.FullName)\AppData\Roaming\1C\1CEStart\*.v8i"} -ErrorAction SilentlyContinue -File)
{
    $save   = $false
    $config = Get-Content -Path $v8i_file -Encoding UTF8
    
    ForEach ($base in $base_list)
    {
        $Pattern = "^Connect=Srvr=.+;Ref=`"$($base.СтароеНазваниеБазы)`";$"
 
        if ($config -match $Pattern)
        {
            $config = $config -replace $Pattern,"Connect=Srvr=`"$($base.НовыйСервер)`";Ref=`"$($base.НовоеНазваниеБазы)`";"
            $save = $true
        }
    }
 
    if ($save)
    {
        Copy-Item -Path $v8i_file -Destination "$($v8i_file.FullName).bak"
        $config | Set-Content -Path $v8i_file -Encoding UTF8
    }
}
0
dj-12l
0 / 0 / 0
Регистрация: 22.02.2016
Сообщений: 28
12.09.2019, 16:18  [ТС] 19
О, круто. Вроде как работает! Спасибо.
вообще я имел ввиду в отдельно место скопировать файл т.к. как потом поймешь у кого требовалось заменять, а у кого нет?
или может записать в файл лог у кого производилась замена. например

PowerShell
1
2
3
4
5
6
 if ($save)
    {
        Copy-Item -Path $v8i_file -Destination "$($v8i_file.FullName).bak"
        $config | Set-Content -Path $v8i_file -Encoding UTF8
        ($v8i_file.FullName) | set-content c:\backup\log.txt
    }
0
KDE777
1600 / 1026 / 403
Регистрация: 22.01.2016
Сообщений: 2,850
12.09.2019, 16:41 20
Цитата Сообщение от dj-12l Посмотреть сообщение
вообще я имел ввиду в отдельно место скопировать файл
Делайте. Думаю, что от реализации копирования файлов средствами PS у вас ничего не закипает

Цитата Сообщение от dj-12l Посмотреть сообщение
или может записать в файл лог у кого производилась замена
А можно, до изменения, копировать все v8i-файлы в один каталог, добавляя к названию имя профиля (пользователя):

PowerShell
1
2
3
4
ForEach ($v8i_file in Get-ChildItem -Path $users_path -Directory | Get-ChildItem -Path {"$($_.FullName)\AppData\Roaming\1C\1CEStart\*.v8i"} -ErrorAction SilentlyContinue -File)
{
    Copy-Item -Path $v8i_file.FullName -Destination "c:\backup\$(($v8i_file.FullName -split '\\')[2])_$($v8i_file.Name)"
}
Добавлено через 4 минуты
Цитата Сообщение от dj-12l Посмотреть сообщение
($v8i_file.FullName) | set-content c:\backup\log.txt
1. Тут не нужны скобки
2. Вместо Set-Content, используйте Add-Content иначе в log.txt получите только одну запись, т.к. при изменение каждого v8i-файла log.txt будет перезаписан.
0
12.09.2019, 16:41
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.09.2019, 16:41

Сравните пожалуйста операторы ветвления в скрипт-файле и файле-функции
Приятного времени суток господа. Есть маленький вопрос, даже недоумение. Вот оно: Если я...

Bash - скрипт для бэкапа баз Mysql
Решил попробовать написать скрипт бакапа баз Mysql нашел команду бакапа одной базы mysqldump...

Создание баз данных c использованием CASE средств
Всем привет! У меня тема диплома &quot;Проектирование баз данных используя CASE средств&quot;. У меня будет...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.