2016-04-12 6 views
2

Эксел парень, который иногда превращается в автоматизацию через vba.Возврат дубликатов имен (включая частичные совпадения)

Я попытался решить https://stackoverflow.com/q/36538022/641067 (теперь закрыт) и не смог попасть туда с моим основным знанием powershell и googlefu.

В сущности проблема ФП представлены в:

  1. Есть список имен в виде текстового файла.
  2. Цель состоит в том, чтобы отображать только те имена, которые встречаются хотя бы один раз (так что отбросьте уникальные имена, см. Пункт (3)).
  3. Имена, встречающиеся хотя бы один раз, включают частичные совпадения, то есть Will и William можно рассматривать как дубликаты и должны быть сохранены. Принимая во внимание, что Билл не является дубликатом William.

Я пробовал различные подходы, в том числе

  • Group
  • Compare-Objectпример ниже

Но я был загнаны в части (3). Я подозреваю, что для этого требуется петля, но мне любопытно, существует ли прямой подход Powershell,

Ждем ваших слушаний от экспертов.

что я пытался

$a = Get-Content "c:\temp\in.txt" 
$b = $a | select -unique 
[regex] $a_regex = ‘(?i)(‘ + (($a |foreach {[regex]::escape($_)}) –join “|”) + ‘)’ 
$c = $b -match $a_regex 
Compare-object –referenceobject $c -IncludeEqual $a 
+0

Считаете ли вы * Andrew * and * Allice * дубликатами? Или, другими словами, сколько должно быть LCS или сходство? –

+1

Если одно текстовое поле полностью помещается внутри другого (начиная с LHS), вы можете считать его обманом. Так Уилл является дубликатом Уильяма, но Билла нет. – brettdj

+1

В соответствии с этими правилами вы можете отсортировать список и вывести результаты поиска следующего регулярного выражения: '^ (\ w +) $ \ n \ 1', чтобы сохранить только дубликаты. –

ответ

3

После testscript с помощью цикла будет работать правилами, изложенными и выглядит несложный мне

$t = ('first', 'will', 'william', 'williamlong', 'unique', 'lieve', 'lieven') 
$s = $t | sort-object 

[String[]]$r = @() 
$i = 0; 
while ($i -lt $s.Count - 1) { 
    if ($s[$i+1].StartsWith($s[$i])) { 
     $r += $s[$i] 
     $r += $s[$i+1] 
    } 
    $i++ 
} 
$r | Sort-Object -Unique 

и ниже testscript с использованием регулярных выражений может вы начали ,

$content = "nomatch`nevenmatch1`nevenmatch12`nunevenmatch1`nunevenmatch12`nunevenmatch123" 

$string = (($content.Split("`n") | Sort-Object -Unique) -join "`n") 
$regex = [regex] '(?im)^(\w+)(\n\1\w+)+' 
$matchdetails = $regex.Match($string) 
while ($matchdetails.Success) { 
    $matchdetails.Value 
    $matchdetails = $matchdetails.NextMatch() 
} 
+0

Это замечательно - большое спасибо. Как примечание стороны не должно * nunevenmatch123 * также было совпадением? – brettdj

+0

Да, это должно быть, но это проблема с решением regex. Если вы добавите uneventmatch1234, вы увидите, что это решение вернет правильный результат * (так как есть четное количество совпадений) *. Мне еще не удалось выяснить, как решить эту проблему. –

+0

Двигатель regex находит совпадение * (содержит две строки) и продолжает поиск после окончания матча ... –

Смежные вопросы