Назад | Перейти на главную страницу

Задача Powershell

Друг попросил меня сделать следующее:

«Найдите самый быстрый и простой способ сортировки списка каталогов по ПОСЛЕДНЕМУ символу в именах файлов».

Он сделал это в Linux, используя следующее:

ls | rev | sort | rev 

Я хотел бы показать ему альтернативу PowerShell, но я только начинаю изучать Powershell и не могу этого сделать. Итак, я обманываю и прошу вашей помощи.

Вы можете попробовать это:

dir| sort {$_.name[-1]}

К сожалению, в Powershell нет удобного простого обратного метода, поэтому вместо этого вам нужно получить последнюю букву строки и отсортировать по ней. Я сделал это одним из способов:

dir| sort {$_.name.Substring($_.name.length-1)}

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

dir | sort -Property @{Expression ={$n = $_.Name.ToCharArray(); [Array]::Reverse($n);[String]::Join("",$n)}}

Не такой короткий, как версия для unix, в основном потому, что в .NET Framework нет функции String.Reverse (). В основном это работает, сообщая sort «сортировать, вычисляя это выражение для входных аргументов».


Теперь, если какая-либо оболочка unix работает лучше, чем

dir | sort -Property Length -Descending

чтобы сначала распечатать все файлы с самым большим, мне было бы интересно его увидеть.

Я уверен, что кто-то может сделать это лучше, но вот один способ, полностью совместимый с lynix. Он имеет то преимущество, что оставляет вам многоразовый rev строковая функция для вашего инструментария, т.е. сортирует всю строку, а не только последний символ:

function rev ($s) {return -join ($s[$s.Length..0])}

dir | foreach{rev($_.name)} | sort | foreach{rev($_)}

Я думаю, что здесь foreach хорошо демонстрирует, что конвейеры PowerShell являются массивами, а не просто строками, как в * nix.

Мне потребовалось некоторое время, чтобы понять, что мне нужно было использовать только $_ и нет $_.name внутри 2-го foreach. Итак, я кое-что узнал об изменениях содержимого массива от одного канала к другому.

* Благодарность за мою интуицию функции rev идет на http://rosettacode.org/wiki/Reverse_a_string#PowerShell


Работает как lynix:

  • dir | sort -Property @ {Выражение = {$ n = $ _. Name.ToCharArray (); [Массив] :: Reverse ($ n); [String] :: Join ("", $ n)}}

Вроде работает как lynix, но очень и очень медленно:

  • ls -n | sort {$ _ [3e3..0]}

Не работай как lynix, т.е. не удается отсортировать все символы в именах файлов; (сортирует только самый последний символ строки):

  • dir | сортировать {$.name.Substring ($.name.length-1)}
  • dir | сортировать {$ _. name [-1]}
  • ls | sort {$ _. Имя [-1]}
  • ls | sort {"$ _" [- 1]}
  • ls -n | sort {$ _ [- 1]}

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

ls|sort{$_.Name[-1]}

Также вы можете использовать (сокращенно) -Name аргумент Get-ChildItem:

ls -n|sort{$_[-1]}

который вернет строки напрямую.

Если вы действительно хотите сортировать по обеспечить регресс строка, то работает (но медленно) следующее:

ls -n|sort{$_[3e3..0]}

Вы можете сделать это быстрее, если у вас есть верхняя граница длины имени файла.

ls|sort{"$_"[-1]}