none
[powershell] Поиск с заменой RRS feed

  • Вопрос

  • Всем привет!

    Как выполнить поиск с заменой в xml. Ниже я привел рабочую строку, которая выполняет данную операцию. Нужно только немного доработать. В начальной строке где ип вида (192.168..) нужно добавить какой нибудб параметр, для замены всего что он там встретит. Пробовал * , ругается на синтакс. Заранее спасибо за помощь.  

    (Get-Content 2.xml) -replace '<Column id="8" name="HostName">192.168.</Column>',

    '<Column id="8" name="HostName">ip</Column>' | Set-Content -path 3.xml;

    19 марта 2012 г. 13:57

Ответы

  • Kazun, это регулярные выражения, так что тут заменится даже 1924168 и всё что будет идти после этой строки:

    PS C:\Users\xaegr> "Phone: 1-192-168, IP: 10.10.1.1, Mask 255.255.255.0" -replace '192.168.*',"192.168.0.0"
    Phone: 1-192.168.0.0

    bobgreen84, отлично, но какую смысловую нагрузку несут круглые скобки (capture groups) если ничего захватывать тут не требуется?

    Учитывая то что поле HostName, как мне кажется, может включать не только IP-адреса, вот так было бы правильнее:

    (Get-Content 2.xml) -replace '<Column id="8" name="HostName">[^<]*</Column>',
    '<Column id="8" name="HostName">ip</Column>'  | Set-Content -path 3.xml;


    AKA Xaegr, MVP: PowerShell Блог: http://xaegr.wordpress.com

    • Помечено в качестве ответа windavoz 20 марта 2012 г. 11:41
    19 марта 2012 г. 15:45
    Модератор
  • Сделал по другому с маленькими файлами работает.

    # dir $dir="c:\tmp\" # contents of a directory $items = Get-ChildItem -Path $dir # enumerate the items array foreach ($item in $items) { # if the item is NOT a directory, then process it. if ($item.Attributes -ne "Directory") { #replace Logs $fileName=$item.Name (Get-Content -Path "$dir$fileName") -replace '<Column id="8" name="HostName">[^<]*</Column>', '<Column id="8" name="HostName">HostName</Column>' | Set-Content -Path "$dir$fileName.new"; } }

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

    Get-Content : Выдано исключение типа "System.OutOfMemoryException".
        + CategoryInfo          : NotSpecified: (:) [Get-Content], OutOfMemoryException
        + FullyQualifiedErrorId : System.OutOfMemoryException,Microsoft.PowerShell.Commands.GetContentCommand

    Как решить проблему? Спасибо.

    • Помечено в качестве ответа windavoz 20 марта 2012 г. 11:41
    20 марта 2012 г. 10:28
  • Попробовать использовать Foreach:

    Get-Content -Path "$dir$fileName" -ReadCount 1000 | Foreach {
    	$_ -replace '<Column id="8" name="HostName">[^<]*</Column>', '<Column id="8" name="HostName">HostName</Column>' | Add-Content "$dir$fileName.new"
    }

    • Помечено в качестве ответа windavoz 20 марта 2012 г. 11:40
    20 марта 2012 г. 10:49
    Отвечающий

Все ответы

  • 192.168.*
    19 марта 2012 г. 14:08
    Отвечающий
  • Попробуйте так:

    -replace "(192)\.(168)\.(\d){1,3}\.(\d){1,3}","ip"

    19 марта 2012 г. 14:09
  • Kazun, это регулярные выражения, так что тут заменится даже 1924168 и всё что будет идти после этой строки:

    PS C:\Users\xaegr> "Phone: 1-192-168, IP: 10.10.1.1, Mask 255.255.255.0" -replace '192.168.*',"192.168.0.0"
    Phone: 1-192.168.0.0

    bobgreen84, отлично, но какую смысловую нагрузку несут круглые скобки (capture groups) если ничего захватывать тут не требуется?

    Учитывая то что поле HostName, как мне кажется, может включать не только IP-адреса, вот так было бы правильнее:

    (Get-Content 2.xml) -replace '<Column id="8" name="HostName">[^<]*</Column>',
    '<Column id="8" name="HostName">ip</Column>'  | Set-Content -path 3.xml;


    AKA Xaegr, MVP: PowerShell Блог: http://xaegr.wordpress.com

    • Помечено в качестве ответа windavoz 20 марта 2012 г. 11:41
    19 марта 2012 г. 15:45
    Модератор
  • Автор просит захватывать строки "где ип вида (192.168..)". Скобки в принципе в данном случае не нужны, но мало ли какие еще IP потребуется заменить :)

    19 марта 2012 г. 17:51
  • Спасибо. Может я не понятно рыразился )). Мне нужно строку '<Column id="8" name="HostName">Что-то</Column>', заменить на '<Column id="8" name="HostName">Мое значение</Column>'.  Причем где 'что то' может быть любое значение не только ип.

    20 марта 2012 г. 5:45
  • $xml = [xml](Get-Content C:\2.xml)
    $xml.GetElementsByTagName("Column") | Where {$_.id -eq "8"} | Foreach {$_."#text" = "Мое значение"}
    $xml.Save("C:\3.xml")

    20 марта 2012 г. 8:43
    Отвечающий
  • Сделал по другому с маленькими файлами работает.

    # dir $dir="c:\tmp\" # contents of a directory $items = Get-ChildItem -Path $dir # enumerate the items array foreach ($item in $items) { # if the item is NOT a directory, then process it. if ($item.Attributes -ne "Directory") { #replace Logs $fileName=$item.Name (Get-Content -Path "$dir$fileName") -replace '<Column id="8" name="HostName">[^<]*</Column>', '<Column id="8" name="HostName">HostName</Column>' | Set-Content -Path "$dir$fileName.new"; } }

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

    Get-Content : Выдано исключение типа "System.OutOfMemoryException".
        + CategoryInfo          : NotSpecified: (:) [Get-Content], OutOfMemoryException
        + FullyQualifiedErrorId : System.OutOfMemoryException,Microsoft.PowerShell.Commands.GetContentCommand

    Как решить проблему? Спасибо.

    • Помечено в качестве ответа windavoz 20 марта 2012 г. 11:41
    20 марта 2012 г. 10:28
  • Попробовать использовать Foreach:

    Get-Content -Path "$dir$fileName" -ReadCount 1000 | Foreach {
    	$_ -replace '<Column id="8" name="HostName">[^<]*</Column>', '<Column id="8" name="HostName">HostName</Column>' | Add-Content "$dir$fileName.new"
    }

    • Помечено в качестве ответа windavoz 20 марта 2012 г. 11:40
    20 марта 2012 г. 10:49
    Отвечающий
  • Всем спасибо!
    20 марта 2012 г. 11:41