2016-07-29 3 views
4

Das folgende Skript funktioniert gut, wenn der Dateiname in der Befehlszeile angegeben wird.Erste Schritte im Powershell-Stream

tail.bat
@echo off 
set "COUNT=%1" 
set "COUNT=%COUNT:-=%" 
set "FILENAME=%~2" 
powershell "Get-Content %FILENAME% -Last %COUNT%" 

Aber was ich brauche, ist der Text in Get-Content von stdin Rohr zu können. Ich möchte Folgendes schreiben, um die letzten drei Subversion-Tags zu erhalten, die dem Projekt zugewiesen sind. Was kann ich tun, um die Quelle auf Get-Content zu stdin zu bekommen?

svn ls svn://ahost/arepo/aproject/tags | call tail.bat -3 

NB: Ich bin keine hilfreichen Tools wie tail von außen zu installieren gestattet. Dies muss mit den Programmen geschehen, die bereits auf der Maschine verfügbar sind.

Antwort

6

Rewrite tail.bat wie folgt: Dadurch wird Powershell stdin Eingabe über $Input, wenn kein Dateiname-Argument übergeben wurde, mit freundlicher Genehmigung von this answer lesen

@echo off 

set "COUNT=%1" 
set "COUNT=%COUNT:-=%" 
set "FILENAME=%~2" 

if "%FILENAME%"=="" (
    powershell -noprofile -command "$Input | Select-Object -Last %COUNT%" 
) else (
    powershell -noprofile -command "Get-Content \"%FILENAME%\" -Last %COUNT%" 
) 

.

Beispiel:

C:> (echo one & echo two & echo three) | tail.bat -2 
two 
three 

Anmerkung:

  • Während Power allgemein die Pipeline und gibt Gegenstände jeglicher Art, an die Außenwelt ihre Schnittstelle ausnahmslos beinhaltet sendet durch Zeichenketten.

  • So, da $Input ist ein enumerator die außerhalb stdin Eingang darstellt, können wir sicher sein, dass es die Eingabetextzeilen (als Strings) aufzählt eins nach dem anderen, so alles, was wir brauchen ist wählen Sie die Linien von Interesse, weshalb Rohrleitungen zu Select-Object ist ausreichend.

  • dagegen eine Datei namentlich in Powershell zu lesen erfordert Get-Content (die, nebenbei bemerkt, sendet es auch, die Linien der Eingabedatei von einem durch die Pipeline, es sei denn, Sie auch -Raw angeben); seit Get-Content hat tail Funktionalität eingebaut, über Parameter -Tail (und sein Alias ​​-Last), ist alles, was hier benötigt wird.

  • CAVEAT: Charakter Decodierung am Eingang und Re-Encoding auf Ausgabe beteiligt ist, wenn Powershell mit der Außenwelt spricht:

    • Wenn Sie immer nur mit ASCII-codierten Eingabe zu tun (Einzelbyte-Zeichen mit Codepunkten zwischen 0 und 127), brauchen Sie sich keine Sorgen zu machen.

    • Andernfalls bereiten Sie sich auf eine Welt des Schmerzes vor - siehe unten für Details.


Dekodierung/Re-Encoding Probleme

  • Unter der Annahme, dass Powershell Ihre Eingang Codierung (siehe unten) erkennt, die Ausgang Codierung ist immer was die Konsolenfenster 's zugeordnete Codierung ist; standardmäßig ist dies die OEM-Codepage (z. B. die "DOS" -Codeseite CP437 in US-englischen Systemen), die in PS als [Console]::OutputEncoding wiedergegeben ist.

    • So mit richtig erkannt Eingang, wenn Sie an die Konsole drucken, werden die Dinge aussehen OK, aber wenn Sie die Ausgabe in einer Datei erfassen, werden Sie mit einer OEM-Codepage Ende -kodierte Datei, die wahrscheinlich unerwünscht ist.

    • Wenn möglich, könnten Sie grundsätzlich Ihre Konsolenfenster einrichten, um Ihre Codepage (Eingang und Ausgabecodierung) die Wahl zu verwenden (mit chcp), sondern versuchen, die Codierung Ad-hoc-Änderungen in Ihrem Skript ist leider keine Option.
      Beachten Sie, dass die Verwendung von UTF-8 - Codepage 65001 - nur funktioniert, wenn Sie Ihre Konsolenfenster für die Verwendung einer der TT (TrueType) -Schriften konfigurieren.

  • Wie oben geschrieben, der Satz von Eingangs Codierungen, die korrekt erkannt werden leider beschränkt auf die folgenden wird, basierend auf dem Standard-Eingabecodierung (die auch die OEM-Codepage ist, spiegelt sich in PS als [Console]::InputEncoding; erinnern: Eingabe wird neucodierten auf Ausgang):

    • ASCII Eingang (Neucodierung am Ausgang wird durch Standard bewahren diese enc oding)
    • UTF-16 LE Eingang mit eine BOM (das ist, was Powershell ruft Unicode vorbehaltlich Re-Encoding, um etwas potenziell verschiedene auf Ausgang)
  • Sie konnte Hart- Code eine erwartete Eingabe Codierung durch Hinzufügen von -Encoding <enc> zum Get-Content Aufruf (die standardmäßig die Windows-Standardcodepage-Codierung erwartet), aber das gleiche für stdin Eingabe (wie in $Input) wäre nicht trivial.

    • z., Mit der Standard-Eingabecodierung, wenn Sie explizit die Eingabe als UTF-8 (auch hier beachten, dass auf Ausgang[Console]::OutputEncoding Codierung angewandt wird) interpretieren wollten:
      powershell -noprofile -command "$Input | % { [text.encoding]::utf8.GetString([Console]::InputEncoding.GetBytes($_)) } | Select-Object -Last %COUNT%"
+0

Danke. Ich habe etwas über "$ Input" und "Select-Object vs. Get-Content" zu lernen. – lit

+0

Mein Vergnügen; schau, ob mein Update hilft; Beachten Sie die Einschränkungen bei der Eingabedecodierung/-ausgabe. – mklement0

+1

Danke für den Zusatz. Ich bin mit Codierungsproblemen vertraut, da ich DOS- und Windows-Programme auf japanischen Rechnern ausführen ließ, bevor Unicode existierte. Viel Spaß. – lit