2016-12-02 2 views
0

Я использую PowerShell для сравнения двух строк с амперсандом (&) в них (т. Е. Строка «Политики & Процедуры»).Как сравнить строки, которые имеют амперсанд в них в PowerShell

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

"Policies & Procedures" 
'Policies & Procedures' 
"'Policies & Procedures'" 

кода я использую для сравнения строк:

if ($term1 -eq $term2) { 
    do something 
} 

Проверка строки визуально - они идентичны, однако оператор if никогда не оценивает истину. Есть ли способ сравнить эти две строки так, чтобы он оценивал значение true?

EDIT

Контекст, в котором я делаю эту строку сравнить ищет термин имени в систематике для сайта SharePoint. Вот код, я использую:

function getTerm($termName) { 

    foreach($term in $global:termset.Terms) { 
    $termTrimmed = $term.Name.trim() 
    Write-Host "term name = $termTrimmed" -foregroundcolor cyan 
    if ($termTrimmed -eq $termName) { 
     return $term 
    } 
    } 
    return null 
} 

Я напечатал как term.Name и termName к экрану, и они идентичны. Если в строке нет амперсанда, эта функция работает. Если есть амперсанд, эта функция не работает. Вот как я знаю, амперсанд - проблема.

+0

Только что попробовал приведенный ниже код, и он вернул '$ true', как и ожидалось, вы можете показать код, который генерирует ваши строки? '$ term1 = 'Политика и Procedures'' ' $ term2 =' Политика и Procedures'' '$ term1 -eq $ term2' –

+0

же, возвращает' $ true' для меня. – 4c74356b41

+0

Амперсанд [не является особым символом в строках PowerShell] (https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_quoting_rules), что заставляет вас это вызывать как конкретная вещь, вызывающая проблему? – TessellatingHeckler

ответ

1

Это known quirk:

Есть два типа амперсандами, что вам нужно, чтобы быть в курсе, когда играет с SharePoint систематики

Наш любимый и самый любимый

  • & Номер ASCII: 38

И самозванец

  • ASCII Номер: 65286

После прочтения this article по Nick Hobbs, стало очевидно , что при создании термина заменяет 38 амперсанд с 65286 амперсанд.

Это будет проблемой, если вы хотите провести сравнение с исходным кодом (электронной таблицы, базы данных и т. Д.) , так как они больше не являются .

Как подробно описано в статье Ника, вы можете использовать метод TaxonomyItem.NormalizeName создать «таксономическую» версию вашей строки для сравнения:

Try это (не тестировалось на реальных SharePoint):

function getTerm($termName) 
{ 
    foreach($term in $global:termset.Terms) { 
    $termNormalized = [Microsoft.SharePoint.Taxonomy.TaxonomyItem]::NormalizeName($term.Name) 
    if ($termNormalized -eq $termName) { 
     return $term 
    } 
    } 
    return null 
} 
+0

Трудно видеть '65286' как код' ASCII', поскольку ASCII - это 7-битная кодировка. Значение '65286' является кодовым названием Unicode для FULLWIDTH AMPERSAND. – lit

+0

Это гораздо более элегантное решение, чем мое. Спасибо, что опубликовали это! – user5013

1

После преобразования обеих строк в массивы char и сравнения значения unicode амперсандов выявлена ​​проблема. Амперсанд, используемый в строке поиска, имеет значение 38, тогда как амперсанд, возвращаемый из хранилища терминов SharePoint, имеет значение 65286 (называемый полным амперсандом, хотя он выглядит как обычный амперсанд на экране).

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

function getTerm($termName) { 

    $searchChars = $termName.toCharArray() 
    $size = $searchChars.Count; 
    foreach($term in $global:termset.Terms) { 
    $match = $True 
    $chars = $term.Name.trim().toCharArray() 
    if ($size -eq $chars.Count) { 
     for ($i = 0; $i -lt $size; $i++) { 
     if ($searchChars[$i] -ne $chars[$i]) { 
      # handle the difference between a normal ampersand and a full width ampersand 
      $charCode1 = [int] $searchChars[$i] 
      $charCode2 = [int] $chars[$i] 
      if ((($charCode1 -eq 38) -or ($charCode1 -eq 65286)) -and (($charCode2 -eq 38) -or ($charCode2 -eq 65286))) { 
      continue 
      } else { 
      $match = $False 
      break 
      } 
     } 
     } 
    } else { 
     $match = $False 
    } 
    if ($match -eq $True) { 
     return $term 
    } 
    } 
    return $null 
}