Регулярные выражения в powershell split - PullRequest
0 голосов
/ 28 ноября 2018

Мне нужно вычеркнуть имя UNC fqdn, указав только имя или IP, в зависимости от ввода.

Мои примеры будут

\\tom.overflow.corp.com
\\123.43.234.23.overflow.corp.com

Я хочу в итоге просто tom или 123.43.234.23

У меня есть следующий код в моем массиве, который чередуетсядоменное имя идеально, но я все еще остаюсь с \\tom

-Split '\.(?!\d)')[0]

Ответы [ 4 ]

0 голосов
/ 28 ноября 2018

Функция Select-String использует регулярное выражение и заполняет объект MatchInfo совпадениями (которые затем могут быть запрошены).

Регулярное выражение "(\.?\d+)+|\w+" работает для вашего конкретного примера.

"\\tom.overflow.corp.com", "\\123.43.234.23.overflow.corp.com" |
  Select-String "(\.?\d+)+|\w+" | % { $_.Matches.Value }
0 голосов
/ 28 ноября 2018

Я краду Lee_Dailey s $InSTuff, но добавляю RegEx, который я недавно использовал

$InStuff = -split @'
\\tom.overflow.corp.com
\\123.43.234.23.overflow.corp.com
'@
$InStuff |ForEach-Object {($_.Trim('\\') -split '\.(?!\d{1,3}(\.|$))')[0]}

Пример вывода:

tom
123.43.234.23

Как вы можете видеть здесь на RegEx101 точки между числами не соответствуют

0 голосов
/ 28 ноября 2018

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

Вы можете использовать чередование регулярных выражений (|) включить ведущий \\ в начале как дополнительный -split разделитель .

Учитывая, что сопоставление разделителя в самом начале ввода создает пустой элемент с индексом 0, вам нужно получить доступ к индексу 1, чтобы получить интересующую подстроку.

Короче: регулярное выражение, переданное -split, должно быть '^\\\\|\.(?!\d)'вместо '\.(?!\d)', а индекс, используемый для доступа к результирующему массиву, должен быть [1] вместо [0]:

'\\tom.overflow.corp.com', '\\123.43.234.23.overflow.corp.com' | 
  ForEach-Object { ($_ -Split '^\\\\|\.(?!\d)')[1] }

Выше приведено:

tom
123.43.234.23

В качестве альтернативы , вы можете удалить ведущий \\ в отдельном шаге , используя -replace:

'\\tom.overflow.corp.com', '\\123.43.234.23.overflow.corp.com' | 
  ForEach-Object { ($_ -Split '\.(?!\d)')[0] -replace '^\\\\' }

Еще другойальтернатива заключается в использовании одиночной -replace операции , которая не требует ForEach-Object вызова (не требует явной итерации):

'\\tom.overflow.corp.com', '\\123.43.234.23.overflow.corp.com' -replace
  '?(x) ^\\\\ (.+?) \.\D .+', '$1'
  • Встроенный параметр (?x) (IgnoreWhiteSpace) позволяет сделать регулярные выражения более читабельными с незначительным пробелом: любой unescaped пробелы могут использоваться для визуального форматирования.

  • ^\\\\ соответствует \\ (экранировано \) в начале (^) каждогострока.

  • (.+?) лениво соответствует одному или нескольким символам.

  • \.\D соответствует литералу ., за которым следует что-то другие , кроме цифры (\d соответствует цифре, \D - отрицание этого).

  • .+ соответствует одному или нескольким оставшимся символам, т. е.остальная часть ввода.

  • $1 в качестве операнда замены указывает, что 1-я группа захвата ((...)) в регулярном выражении совпала, и, учитывая, что регулярное выражение было разработанопотребляет всю строку, заменяет ее только этим.

0 голосов
/ 28 ноября 2018

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

это избавит от ведущего \\ и затем заменит доменное имя на.

# fake reading in a text file
#    in real life, use Get-Content
$InStuff = -split @'
\\tom.overflow.corp.com
\\123.43.234.23.overflow.corp.com
'@

$DomainName = '.overflow.corp.com'

$InStuff.ForEach({
    $_.TrimStart('\\').Replace($DomainName, '')
    })

вывод ...

tom
123.43.234.23
...