web-dev-qa-db-ja.com

PowerShellで文字列を分割し、各トークンで何かをする

パイプの各行をスペースで分割してから、各トークンを独自の行に印刷します。

私は次を使用してこの結果を得ることができることに気付きます:

(cat someFileInsteadOfAPipe).split(" ")

しかし、もっと柔軟性が欲しい。各トークンでほぼ何でもできるようにしたいです。 (Unixでは AWK を使用していましたが、同じ機能を取得しようとしています。)

私は現在持っています:

echo "Once upon a time there were three little pigs" | %{$data = $_.split(" "); Write-Output "$($data[0]) and whatever I want to output with it"}

明らかに、最初のトークンのみを出力します。トークンごとにfor-eachを実行し、それぞれを順番に印刷する方法はありますか?

また、ブログから入手した%{$data = $_.split(" "); Write-Output "$($data[0])"}パートも、自分が何をしているのか、構文がどのように機能するのかを本当に理解していません。

Googleで検索したいのですが、何と呼べばいいのかわかりません。 GoogleへのWordまたは2つ、または%およびすべての$シンボルが何をするかを説明するリンクと、開き括弧と閉じ括弧の重要性を手伝ってください。

ファイル(または望ましい着信パイプ)に複数の行が含まれているため、実際には(cat someFileInsteadOfAPipe).split(" ")を使用できないことに気付きました。

いくつかの答えについて:

Select-String を使用してトークン化する前に出力をフィルタリングする場合、Select-Stringコマンドの出力は文字列のコレクションではなく、MatchInfoオブジェクトのコレクションであることに注意する必要があります。分割する文字列を取得するには、次のようにLineオブジェクトのMatchInfoプロパティにアクセスする必要があります。

cat someFile | Select-String "keywordFoo" | %{$_.Line.Split(" ")}
54
Pieter Müller
"Once upon a time there were three little pigs".Split(" ") | ForEach {
    "$_ is a token"
 }

キーは$_で、パイプラインの現在の変数を表します。

オンラインで見つけたコードについて:

%ForEach-Object のエイリアスです。角括弧で囲まれたものは、受け取るオブジェクトごとに1回実行されます。この場合、1つの文字列を送信するため、1回だけ実行されます。

$_.Split(" ")は現在の変数を取得し、スペースで分割しています。現在の変数は、ForEachによって現在ループされているものになります。

111
Justus Thane

これを実現する別の方法は、Justus Thaneとmklement0の回答の組み合わせです。 1ライナーの例を見ると、この方法で行うのは意味がありませんが、ファイルまたはファイル名の束を大量に編集しようとすると、かなり便利です。

$test = '   One      for the money   '
$option = [System.StringSplitOptions]::RemoveEmptyEntries
$($test.split(' ',$option)).foreach{$_}

これは次のようになります。

One
for
the
money
1
s31064

Justus Thaneの有用な回答

  • Joey のコメントのように、PowerShellには強力な正規表現ベースの -splitoperator があります。

    • そのunary形式(-split '...')では、-splitawkのデフォルトのフィールド分割のように動作します、つまり:
      • 先頭と末尾の空白は無視されます。
      • 空白(たとえばmultiple隣接するスペース)のrunは、singleセパレータ。
  • PowerShell v4で式ベース-したがって、高速-ForEach-Objectの代替cmdletが利用可能になりました:.ForEach()コレクション "演算子"(メソッド)このブログ投稿.Where()メソッドとともに、Where-Objectのより強力な式ベースの代替手段です。

これらの機能に基づいたソリューションは次のとおりです。

PS> (-split '   One      for the money   ').ForEach({ "token: [$_]" })
token: [One]
token: [for]
token: [the]
token: [money]

前後の空白は無視され、Oneforの間の複数のスペースは単一のセパレータとして扱われたことに注意してください。

0
mklement0