2016-07-29 128 views
4

次のスクリプトは、ファイル名がコマンドラインで指定された場合にうまく機能します。Powershellストリームへの標準入力の取得

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

はしかし、私は必要なものを標準入力からGet-Contentにテキストパイプのことができるようにすることです。プロジェクトに割り当てられた最後の3つのSubversionタグを取得するには、次のように記述します。 Get-Contentへの送信元をstdinにするにはどうすればよいですか?

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

NB:tailのような便利なツールを外部からインストールすることはできません。すでにマシン上で利用可能なプログラムで実行する必要があります。

答えて

6

書き換えtail.batとしては、次のとおりです。

@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%" 
) 

何のファイル名の引数が渡されなかった場合、これは、PowerShellは$Input経由STDIN入力を読み込むthis answerの礼儀を行います。

例:

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

注:

  • PowerShellは、一般的に外界にパイプライン出力を介して任意の種類オブジェクト、そのインターフェイスを送信しながら常にを含みます文字列

  • したがって、$Input外部STDIN入力を表す列挙であることを考えると、我々はそれがは我々が必要ので、すべて、(ストリングのような)入力テキスト行一つずつ列挙ことを確認することができを選択してを選択してください。その理由は、Select-Objectへの配管で十分です。 PowerShellの名前でファイルを読ん対照的に

  • は、(あなたも-Rawを指定しない限り、偶然、また、パイプラインを通して1により、入力ファイルの行を1つずつ送信し、)Get-Contentを必要とします。 Get-Contentには(および別名-Last)というパラメータを使用してtailの機能が組み込まれているため、ここで必要なのはこのすべてです。

  • CAVEAT文字は出力はPowerShellが外の世界と対話する際に関与している上で入力し、再エンコードにデコード:

    • あなたしかASCIIでエンコードされた入力を扱っている場合(コードポイントが0〜127の1バイト文字)、心配する必要はありません。

    • それ以外の場合は、痛みの世界に備えてください。詳しくは、下記を参照してください。


デコード/再エンコードの問題

  • PowerShellは(下記参照)あなたの入力エンコーディングを認識すると仮定すると、出力エンコーディングは必ずです何がコンソールウィンドウの割り当てられたエンコーディングはです。残念ながら、残念ながら、これはPSに[Console]::OutputEncodingとして反映されたOEMコードページ(たとえば、米国英語システムの「DOS」コードページCP437)です。

    • したがって、あなたがコンソールに印刷する場合、正しく認識入力で、物事はOKになりますが、あなたはファイルで出力をキャプチャする場合は、OEM-コードページになってしまいますエンコードされたファイルですが、おそらくこれは望ましくありません。

    • 可能ならば、あなたは基本的にがあなたのコードページ(chcpを使用して)選択した(入力出力エンコーディング)を使用するようにコンソールウィンドウを設定できますが、あなたにエンコーディングアドホックを変更しようとしていますスクリプトは残念ながらオプションではありません。コードページ65001 - - あなたはTT(TrueTypeフォント)フォントのいずれかを使用するようにコンソールウィンドウを設定している場合のみ動作し、UTF-8を使用すること
      注意。

  • 上記記載の通り、正しく認識される入力エンコーディングのセットが、残念ながら[Console]::InputEncodingとしてPSに反映また、OEMコードページで、デフォルトの入力エンコーディング(、に基づいて、以下に限定されます。覚えている:入力)再エンコードに出力あろう:出力に

    • ASCII入力(再符号化は、デフォルトでは、このENCを保存します出力上の潜在的に異なるものに再エンコードの対象、PowerShellはUnicode呼んでBOMは()あなた
  • で)

  • UTF-16 LE入力をodingできハード(デフォルトではWindowsのデフォルトのコード・ページ符号化を期待)Get-Contentコールに-Encoding <enc>を添加することにより、コードが期待入力エンコーディングを、しかしに反映されるように(STDIN入力のために同じことを行います)は自明ではありません。例えば

    • あなたが明示的にUTF-8などの入力を解釈したい場合は、デフォルトの入力エンコーディングで、(再び、[Console]::OutputEncodingエンコーディングが適用され出力であることに注意): powershell -noprofile -command "$Input | % { [text.encoding]::utf8.GetString([Console]::InputEncoding.GetBytes($_)) } | Select-Object -Last %COUNT%"
+0


はありがとうございます。私は '$ Input'と' Select-Object vs. Get-Content'について学びました。 – lit

+0

私の喜び。私のアップデートが役立つかどうかを見てください。入力のデコード/出力の再エンコード警告に注意してください。 – mklement0

+1

ありがとうございます。私は、Unicodeが存在する前にDOSとWindowsプログラムを日本語のマシン上で実行させていたので、エンコードの問題に精通しています。たくさんの楽しみ。 – lit

関連する問題