2009-08-11 14 views
4

タブ区切りのファイルがあります。私は、各行のタブの数を数えるPowerShellスクリプトが好きです。私はこの思い付いた:それはファイルの行数である、3を得ファイルの各行のタブ数をカウントするOneliner

${C:\tabfile.txt} |% {$_} | Select-String \t | Measure-Object | fl count 

私は間違っていることを指摘していますか?ファイルの各行に1つの番号を印刷したいと思います。

答えて

6

あなたのコードにいくつかの問題がありますが、それらはすべてグループ化/アレイ管理/ネストループを中心にしています。

gc test.txt | % { ($_ | select-string `t -all).matches | measure | select count } 
  • 行にテキストファイルを読んだ後、あなたはスクリプトブロックにパイプラインの残りの部分をラップする必要があります。それ以外の場合、下流のコマンドレットは、「現在の」行からどの要素が来たのかを区別できません。 PSパイプラインは、オブジェクトを1つずつ処理することです。ネストされた配列やイテレーターの状態などの概念はありません。ブラインド列挙です。
  • -AllMatchesを指定する必要があります。そうしないと、各行の最初の一致が見つかるとすぐにselect-stringが停止します。このインラインマッチングの「内側の結果セット」を得るために、公式の結果セットからMatchesプロパティを取得する必要があります。
+0

+1。彼の元のコードがうまくいかなかった理由を説明してくれました。おそらく単にソリューションを提供する以外にも役立つでしょう:-)(私もそれをやったことがありましたが、決してSelect-Stringを使用しませんでした:-)) – Joey

+0

scriptblockをいつ使用するかはまだ混乱します。私はまた、両方のソリューションが$ {file.txt}でファイルを消費するのではなくgcを使用することがスタイルの問題であることに気づいたのですか? – JasonHorner

+0

'$ {...}'を使うときは、中括弧の間に完全な絶対パスを入れなければなりません。一方、 'Get-Content'は相対パスを使うことができます。私の場合、私は 'C:\'にユーザファイルを置いていないので、 '$ {C:\ Users \ me \ ...} 'のようになります。 'Home:'ドライブを作りましたが、それでも絶対パスは好きではありません:-)。また、Get-Contentは、何かを見つけることができないときに例外を与えます。これは時々奇妙なエラーをデバッグするのに便利です:-) – Joey

5

最初の試みではなく、非常に洗練された:ここで事実を利用

gc .\tabfile.txt | % { ($_ -split "`t").Count - 1 } 

、私はタブ文字で文字列を分割するときのタブがあるよりも、私は1つの以上のアイテムを持つ配列を取得しますことをこの線。

別のアプローチ、避け分割ライン:

gc .\tabfile.txt | % { ([char[]] $_ -eq "`t").Count } 

文字列はchar[]にキャストすることができます (もToCharArray()方法がある)、その後、私は比較演算子を返すことで、コレクションに異なる動作をするという事実を使用していますブール値ではなく、一致するすべての項目。したがって、そこでの比較では、元の行からすべてのタブを含む配列が返されます。この行から、アイテムの数を取得するだけです。

+0

char []にキャスティングし、-eqを使用して配列を自動的にアンロールするのは巧妙です。 +1 –

+0

Powershellでゴルフを試してみると、そのメリットがあります:-) – Joey

+0

これはおそらく「より良い」回答ですが、他の投稿は私の元々の質問によく答えました。 – JasonHorner

2

別のオプション:

$content = Get-Content file.txt | Out-String 
[regex]::matches($content,"\t").count 
4

そして、まだ別のオプションあなたがV2を実行している場合。

select-string \t c:\tabfile.txt -All | 
    %{"$($_.matches.count) tabs on $($_.LineNumber)"} 
関連する問題