2014/05/02
今日のワンライナー その1:配列から最も要素数の多い要素を取りだす
また続くかどうか不明の新シリーズ。今日書いたワンライナーを記録していきます。
今回は、配列に含まれる要素のうち、もっとも出現頻度の多いものを調べる方法です。たとえば、0, 0, 0, 1, 0, 3, 0, 2, 0, 2という配列がある場合、「0」は6個含まれており最も要素数が多いので、この場合「0」を出力します。
ワンライナーは以下のようになります。(配列変数の宣言を合わせると2ラインですけど)
$array = 0, 0, 0, 1, 0, 3, 0, 2, 0, 2 $array | group | sort Count -Descending | select -First 1 | select -Expand Name
今回のケースのように、「配列内に同一の要素が含まれており、要素ごとに纏める」という手順が必要なときはGroup-Objectコマンドレット(エイリアス:group)の出番です。
$array | group とすると、
Count Name Group ----- ---- ----- 6 0 {0, 0, 0, 0...} 1 1 {1} 1 3 {3} 2 2 {2, 2}
のような出力が得られます。Count=出現回数、Name=要素、Group=該当する要素のリスト です。なのでこの出力だけでお題の解答である「0」が確認できます。あとはこの出力から求める値を抽出するだけです。
Group-Objectコマンドレットの出力はGroupInfoというオブジェクトです。そう、これもオブジェクトなので、他のオブジェクト同様、プロパティ情報を保ったまま後続パイプラインに渡すことができます。
まずSort-Objectコマンドレット(エイリアス:sort)を用いてGroupInfoのCountプロパティの値で降順ソート(-Descendingパラメータ使用)をかけます。するとCountプロパティが一番大きいGroupInfoオブジェクトが一番最初の要素となります。(今回の場合はたまたまソート前後で最初の要素が同じでしたが)
次にSelect-Objectコマンドレット(エイリアス:select)に-First 1と指定することで一番最初のGroupInfoオブジェクトのみ取得します。最後に、GroupInfoオブジェクトのNameプロパティの値だけを取りだすのにSelect-Objectコマンドレットに -ExpandPropertyパラメータを指定します。
ところでGroupInfoオブジェクトのGroupプロパティ、どうせNameと同じものがCount分列挙されるだけじゃないか何の意味が?と思われるかも知れないので補足です。Group-Objectコマンドレットには-Propertyパラメータ(位置パラメータなのでパラメータ名は省略可能)が定義されており、指定すると任意のプロパティ値に基づいてグループ化してくれます。
たとえば
dir | group Extension
とすると、カレントディレクトリに含まれるファイルが拡張子別にグループ化され、以下のような出力が得られます。
Count Name Group ----- ---- ----- 1 .gadget {twitterpost.gadget} 59 .vbs {7zip_fix_archive.vbs, 7zip_store_each.vbs...} 72 .ps1 {cddrive.ps1, clipboard.ps1, cmdlets.ps1...}
このようにGroupプロパティの中身は、指定プロパティ値を持つ要素のグループとなっていることが分かると思います。
-Propertyパラメータには集計プロパティを指定することもできるので、
1..10 | group {if($_ % 2 -eq 0){"偶数"}else{"奇数"}}
Count Name Group ----- ---- ----- 5 奇数 {1, 3, 5, 7...} 5 偶数 {2, 4, 6, 8...}
みたいなこともできたりします。
ちなみにGroup情報が不要であるときは、Group-Objectコマンドレットに -NoElementパラメータを付与すると出力を抑制できます。(この場合、出力はGroupInfoオブジェクトではなく、GroupInfoNoElementオブジェクトとなる)
なんか後半はGroup-Objectコマンドレット特集みたくなってしまいました。ではまた次回。
2010/11/04
11/13 プログラミング生放送勉強会 第6回@大阪 でPowerShellの話をします
11/13 プログラミング生放送勉強会 第6回@大阪 [ショートコーディング,PowerShell 他] - Windows Live
http://co9320.spaces.live.com/blog/cns!F8FA3BD6ABDDDB63!314.entry?sa=909959593
★ PowerShell 基礎文法最速マスター + α
Windows 7 に標準添付されている PowerShell の基礎文法を解説。PowerShell ならではのワンライナー(1行で書くスクリプト)についても紹介予定。
というわけでぜひどうぞ~
当日はニコニコ生放送でも中継される予定です。
元記事:http://blogs.wankuma.com/mutaguchi/archive/2010/11/04/194456.aspx2007/09/13
むたぐち PowerShell訓
みなさんなんだか楽しそうなので私も乗ってみました。テンプレ略
一.PowerShellで一番楽しく立派なことは、パイプラインにオブジェクトが渡ることです。
一.PowerShellで一番みじめなことは、同じことをするのにコマンドプロンプトより時間がかかることです。
一.PowerShellで一番淋しいことは、WSHでいいじゃんと思われることです。
一.PowerShellで一番みにくいことは、usingがないのでクラスを完全修飾名で記述しなければならないことです。
一.PowerShell で一番尊いことは、.NET Frameworkを自在に扱うことです。
一.PowerShell で一番美しいことは、コマンドレットを組み合わせてワンライナーを作ることです。
一.PowerShell で一番悲しいことは、Vistaに標準搭載されなかったことです。
元記事:http://blogs.wankuma.com/mutaguchi/archive/2007/09/13/96071.aspx2007/05/21
PowerShellスクリプトはどう書くのが良いか
.NET
Frameworkをバリバリ使ってC#ライクに書けばわりと見やすいスクリプトが書けるが冗長である。コマンドレットをパイプでつないだり各種演算子を使うと見にくいが簡潔に書ける。
これが本題。
しかし前者のようなスクリプトはC#で書いちゃえばいいじゃんという話だ。csファイルに、コンパイルして実行するVBSでも関連付けておけばよいでしょう。js(JScript.NET)ならクラスを書かないでも大丈夫。COMを使うならスクリプトはWSHでもいい。
そう考えるとやはりPowerShellはコマンドレットとパイプを駆使するのが本道のように思う。ただ、どこまで込み入ったものを書くのか。重要なのは可読性と簡潔性のバランスだ。パイプを多用すれば簡潔だが読みにくい。パイプを使わなければ冗長になる。そのあたりをうまく調整していくのがPowerShell使いの課題だろう。
さて、込み入ったスクリプトの究極例は、込み入ったことを一行のスクリプト(ワンライナーという)にすることだ。これには通常のプログラミングとは違い、頭の体操が必要になってくる。しかも後でみると自分でもわからなかったりする。
なので、保存して実行するならワンライナーにする必要はないように思う。冗長でもわかりやすく書くほうがいい。ワンライナーはあくまでコンソール上で手で打ち込むことに意義があるのではないか。
だが、そのスキルを管理者は身につけるべきなのか?
現実的には、コンソール上でコマンドレットを2,3個のパイプで繋ぐ程度が限界なのではないかと思う。ワンライナーをその場で書くのは相当なスキルが要求されるように思う。ただ、幸いなことにPowerShellにはfunctionやfilterを記述したスクリプトファイルをプロファイルとして読み込むことができるので、込み入った処理はあらかじめ関数化、フィルタ化しておくとよいだろう。そのときはワンライナーである必要はないのは先に述べたとおり。
でもPowerShellのワンライナーを極めた人を見てみたい気もする。UNIX系ではいますよね。私?無理ですよw
というわけでPowerShellスクリプトの考察でした。
元記事:http://blogs.wankuma.com/mutaguchi/archive/2007/05/21/77517.aspx2006/11/07
コマンドレットオンラインヘルプ作成
前回作ったワンライナーは見にくいので、スクリプト(*.ps1)に書き下ろしてみました。今回はabout...help.txtなファイルもHTML化してみました。だいぶ便利になってきましたね。
function Sanitize{ #サニタイズ処理 param ([string]$strSource) return ($strSource.Replace("&","&").Replace("<","<").Replace(">",">")) } # コマンドレットのヘルプのHTMLを作成する get-command -commandtype cmdlet| %{"" + $(Sanitize (get-help $_.Name -detail|out-string)).Replace("`r`n","
"| out-file($_.name + ".html")} #about...help.txtのHTMLを作成する get-childitem -path $pshome\ja -filter about*.txt| %{"
") + "" + (get-content $_.fullname -encoding UTF8|%{$(Sanitize($_))+"
"| out-file($_.name + ".html")} $temp="
"}) + "
- "
# コマンドレットのヘルプのHTMLのインデックスを作成する
get-command -commandtype cmdlet|
%{$temp+="
- " + $_.name + " "} # about...help.txtのHTMLのインデックスを作成する get-childitem -path $pshome\ja -filter about*.txt| %{$temp+="
- " + $_.name + " "} $temp+="
2006/11/01
コマンドレットオンラインヘルプ作成ワンライナー
PowerShellのコマンドレットのヘルプを引くには、get-help コマンド名 -detailなどとしますが、コマンドラインでいちいち打つのは邪魔くさい、一覧のヘルプファイルが欲しい、という場合に便利なワンライナーを書いてみました。
カレントにファイルが作成されますので、適宜cdで移動してください。
コマンドレットのヘルプのHTMLを作成するワンライナー
get-command -commandtype cmdlet|%{"" + (get-help $_.Name -detail|out-string).Replace("&","&").Replace("<","<").Replace(">",">").Replace("`n","
"|out-file($_.name + ".html")}
") +"
HTMLのインデックスを作成するワンライナー
$temp="
- ";get-command -commandtype cmdlet|%{$temp+="
- " + $_.name + " "};$temp+="
これを実行すると、カレントディレクトリに、コマンドレットのヘルプが記述された「コマンドレット名.html」というファイルが、登録されている数だけ作成され、インデックスとなるファイルが「index.html」として作成されます。
あとはindex.htmlを開いて読みたいコマンドレットのリンクをクリックしてください。
関連リンクに実際にリンクを張るなど、改造しだすといろいろできると思いますが、まずはワンライナーとしてここに載せておきます。
Copyright © 2005-2018 Daisuke Mutaguchi All rights reserved
mailto: mutaguchi at roy.hi-ho.ne.jp
プライバシーポリシー