Команда сортировки Powershell не работает должным образом - PullRequest
2 голосов
/ 15 января 2020

Я использовал этот набор команд для проверки команды сортировки символов клавиатуры.

$symb="a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","²","1","2","3","4","5","6","7","8","9","0","°","+","&","é",'"',"'","(","-","è",[regex]::escape('`'),"_","ç","à",")","=","~","#","{","[","|","\","^","@","]","}","$","¨","ˆ","£","¤","ù","*","%","µ","<",",",";",":","!",">","?",".","/","§","€"; $symb|sort|ac file.txt;(gc file.txt)-join""

Вот что я получаю, как в файле, так и на консоли.

'-!"#$%&()*,./:;?@[\]ˆ^_`{|}~¨£¤€+<=>§°µ012²3456789aAàbBcCçDdEeéèfFgGhHIiJjKkLlmMNnOoPpqQRrsStTuUùvVwWXxyYzZ

Примерно в половине случаев пар строчных и прописных букв порядок инвертируется; кажется, что это всегда должно быть «строчными первыми, потом заглавными». Как это можно исправить?

Ответы [ 2 ]

3 голосов
/ 15 января 2020

PowerShell - в отличие от типов NET фреймворка - по умолчанию нечувствителен ; вам нужно выбрать , если вы хотите регистр чувствительное поведение.

В случае Sort-Object вам нужно используйте переключатель -CaseSensitive:

PS> -join ('a', 'B', 'A', 'b' | Sort-Object -CaseSensitive)
aAbB

Как и ожидалось, это приводит к сортировке букв в нижнем регистре сначала , поскольку в (US-Engli sh ) строчные буквы порядка сортировки имеют меньший вес сортировки, чем заглавные буквы - даже при том, что в отношении их Unicode кодовых точек отношение является обратным (например, [int] [char] 'a' равно 97, тогда как [int] [char] 'A' равно 65).

(Сортировка на основе кода будет применяться, если массив содержит [char] экземпляров, но PowerShell не имеет литералов [char], поэтому такой литерал, как 'a', равен [string] длина 1; вы можете использовать явные приведения, однако: -join ([char] 'A', [char] 'a' | Sort-Object -CaseSensitive) дает 'Aa', то есть сортирует в верхнем регистре первый.)


без -CaseSensitive, строчные и прописные варианты данной буквы имеют одинаковый вес сортировки, поэтому никакой особый порядок среди них не гарантирован.

Например, следующий l oop быстро завершается:

$prevResult = $null
while ($true) { 

  # Get a shuffled array of lower- and uppercase letters.
  $arr = 'a', 'B', 'A', 'b'
  $arr = $arr | Get-Random -Count $arr.Count

  # Sort it case-INsensitively.
  $result = -join ($arr | Sort-Object)

  $result # output

  # See if the result is different from the previous one.
  # Note the use of -cne rather than just -ne:
  # -ce is the case-*sensitive* variant of -ne
  if ($prevResult -and $prevResult -cne $result) {
    Write-Warning "Output order has changed."
    break
  }
  $prevResult = $result

} 

Однако обратите внимание, что Sort-Object, по-видимому, выполняет stable sort: то есть с заданным входным массивом результирующий массив всегда одинаков. То есть, если вы переместите создание $arr за пределы while l oop, результат всегда будет одинаковым, а l oop никогда не завершится.

1 голос
/ 15 января 2020

Способ. net не имеет этой проблемы.

$symb = "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "²", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "°", "+", "&", "é", '"', "'", "(", "-", "è", [regex]::escape('`'), "_", "ç", "à", ")", "=", "~", "#", "{", "[", "|", "\", "^", "@", "]", "}", "$", "¨", "ˆ", "£", "¤", "ù", "*", "%", "µ", "<", ",", ";", ":", "!", ">", "?", ".", "/", "§", "€"; 
[Array]::Sort($symb)
$symb
...