Sfida Powershell


7

Sono stato sfidato da un amico a fare quanto segue:

"Trova il modo più rapido e semplice di ordinare un elenco di directory in base all'ULTIMO carattere dei nomi dei file."

L'ha fatto su Linux usando il seguente:

ls | rev | sort | rev 

Vorrei mostrargli l'alternativa PowerShell, ma sto solo iniziando a imparare PowerShell e non riesco a farlo. Quindi, sto tradendo e chiedendo il tuo aiuto.


1
In realtà questo lo sta ordinando non solo per l'ultimo carattere ma per tutti i personaggi seguenti. La risposta di Sam Cogan di seguito è rigorosamente dell'ultimo personaggio e ignora i seguenti caratteri.
Sim

Prima che qualcuno voti per migrare di nuovo questa domanda, dai un'occhiata a questo: meta.stackexchange.com/questions/32471/…
raven,

Penso che questa sfida sia fuorviante e inoltre non sia un confronto equo tra Linux e PowerShell. Se il rev dovesse ordinare solo l'ultimo personaggio, sarebbe giusto. Inoltre ciò che potrebbe essere più giusto sarebbe chiedere alle persone di scrivere bash o altro per ordinare solo l'ultimo carattere, e non semplicemente fare: "ls | rev | sort | ls". Ma onestamente, perché qualcuno vorrebbe questa strana funzione, mi sto ancora grattando la testa, tranne forse per provare a convincere qualcuno che PowerShell può essere compatto come sh, ma con un confronto tra mele e arance?
Vista ellittica il

Risposte:


3

Sfortunatamente Powershell non ha un metodo inverso facile, quindi devi prendere l'ultima lettera della stringa e ordinarla per quella. Questo è un modo in cui l'ho fatto:

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

Come è stato sottolineato, questo sarà ordinato rigorosamente solo dall'ultima lettera, mentre io la versione Linux ordinerà dall'ultima e quindi dalle lettere successive, quindi potrebbe esserci un modo migliore per farlo, o potresti dover introdurre alcuni loop se lo vuoi in questo modo.


Questo è geniale. Non breve come l'alternativa Linux, ma comunque abbastanza buono.
Richard,

Ho notato anche che questo ordina solo per l'ultima lettera, a differenza della versione di Linux. Tuttavia, la sfida dichiarata "dall'ULTIMO personaggio", quindi questa risposta risponde alla domanda, anche se le due soluzioni non sono uguali.
Richard,

A causa di un po 'di confusione, questa domanda è stata migrata su Stack Overflow e quindi non migrata. Keith Hill su Stack overflow ha aggiunto la risposta più breve ls | sort {"$ _" [- 1]}
Richard


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

Non breve come la versione unix, soprattutto perché non esiste una funzione String.Reverse () in .NET Framework. Fondamentalmente funziona dicendo "ordina calcolando questa espressione sugli argomenti di input".


Ora, se una shell unix fa meglio di

dir | sort -Property Length -Descending

per stampare prima tutti i file con il più grande, sarei interessato a vederlo.


4
Che ne dici di 'ls -S'?
Bryan,

Wow! Non sapevo di questo: D Bello :)
AntonioCS il

2

Sono sicuro che qualcuno può farlo meglio, ma ecco un modo che è pienamente compatibile con Lynix. Ha il vantaggio di lasciarti con una revfunzione di stringa riutilizzabile per il tuo toolbox, cioè ordina l'intera stringa e non solo l'ultimo carattere:

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

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

Penso che foreach abbia dimostrato bene come le pipe di PowerShell siano array e non semplicemente stringhe come in * nix.

Mi ci è voluto un po 'di tempo per capire che dovevo usare solo $_e non $_.nameall'interno del 2 ° foreach. Quindi ho imparato qualcosa sulle variazioni del contenuto dell'array da una pipe alla successiva.

* Il credito per il coraggio della mia funzione rev va a http://rosettacode.org/wiki/Reverse_a_string#PowerShell


Funziona come Lynix:

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

In un certo senso funziona come Lynix, ma molto, molto lentamente:

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

Non funzionano come Lynix, ovvero non riescono a ordinare tutti i caratteri dei nomi dei file; (ordina solo l'ultimo carattere della stringa):

  • dir | ordina {$ .name.Substring ($ .name.length-1)}
  • dir | ordina {$ _. name [-1]}
  • ls | sort {. $ _ Nome [-1]}
  • ls | sort { "$ _" [- 1]}
  • ls -n | sort {$ _ [- 1]}

Questo potrebbe essere migliorato facendo accettare alla matrice la funzione rev. Quindi è possibile eliminare forEach nel codice, come la chiamerebbe la funzione. Puoi aggiungere un paio di cose per renderlo ls | rev | sort | revcompletamente valido da solo. :-)
Cory Knutson,

1

La variante di Shay è molto più breve della risposta accettata indicizzando nella stringa ma anche quella può essere migliorata. Puoi accorciarlo ancora di più escludendo spazi non necessari e utilizzando un alias più breve:

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

Inoltre puoi usare l' -Nameargomento (abbreviato) per Get-ChildItem:

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

che restituirà direttamente le stringhe.

Se vuoi davvero ordinare in base alla stringa inversa , allora il seguente funziona (ma è lento):

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

Puoi renderlo più veloce se hai un limite superiore sulla lunghezza del nome del file.


Citando la domanda: »Trova il modo più rapido e semplice di ordinare un elenco di directory in base all'ULTIMO carattere dei nomi dei file.«. Deve solo ordinare in base all'ultimo personaggio. Se il modo più semplice per farlo è invertire la stringa, così sia, ma se il modo più semplice per farlo è semplicemente l'ordinamento in base all'ultimo carattere, anche questo risolve il compito. La domanda non riguardava »Come posso fare esattamente questo frammento di shell Unix in PowerShell?«.
Joey,

Scusate. Ho sbagliato.
Vista ellittica il

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.