Author Archives: AKIYAMA

2017-10-17

PowerShellについて少しは真面目に調べてみた

ちょっとした変換作業を効率化するためにbatを書いていたらファイル名の扱いで困った(空白を含むパスやネットワークパスの扱いが絶望的に面倒くさい)ので代わりにPowerShellでやったら(前回)すんなりうまくいったので 、気をよくしてPowerShellについて少しは真面目に勉強してみました。PowerShellってとっつきにくくて何となく見よう見まねで細部は気にせず適当にやり過ごしていたのですが、知らずに使うのも気持ちが悪いですし。

資料

PowerShellの何が分かりづらいって公式のドキュメントが不足していることですよね。特に言語仕様。結構独特な文法やセマンティックスを持っているのでその辺りの説明が必要です。

探してみると次の場所に3.0の言語仕様書があります(docx形式です)。

最新版は見当たりませんが、この手の仕様書は昔のバージョンの方がシンプルで見やすかったりもしますし我慢します。

日本語で簡単にまとめてくださっているサイトとしては次のサイトがありました。

公式っぽいところだと次のサイトが結構重要なことを書いている気がします。

パイプラインとコマンド実行と関数呼び出し

言語仕様のイントロダクションにも書いてあることですが、PowerShellでとても重要なのはパイプラインだと思います。従来のシェルスクリプトはコマンドの実行によって生じたテキストが次のコマンドへパイプでつながれていきます。しかしPowerShellではコマンドの実行結果はオブジェクトであり、それが次のコマンドへ流れていきます。この一連のオブジェクトが流れる道をパイプラインと呼びます。

PowerShellでのコマンドは、外部のスクリプトや実行ファイルだけでなくユーザーが定義した関数なども含まれます。

コマンドを実行する方法はいくつかありますが、基本的には「コマンド名 引数1 引数2 …」という単純な構文を使います。言語仕様のexpressionを見ても式の中に関数呼び出し構文というのがありません。関数もコマンドですから、式の中ですらカッコで囲んでこの構文を使って呼び出します(メソッド呼び出し構文は式の中にあります。「オブジェクト . メソッド (引数…)」みたいなやつ)。

例えば次のようなtupleという関数。この関数は引数で指定した二つの数を要素とする配列オブジェクトをパイプラインへ出力します。

function tuple($a, $b){$a,$b}

この関数を呼び出すには次のようにコマンドと同じように実行します。

tuple 2 3 #結果は (2, 3) というArray

コマンドを実行した結果、(2, 3)という2要素の配列(Array)オブジェクトが生じるのですが、特に行き先が指定されていないのでコンソールに表示されます。

tuple 2 3 > result.txt

このようにリダイレクトすれば結果をファイルへ出力することも出来ます。

次のように式の中からコマンドを実行して結果を演算することも出来ます。

(tuple 2 3) * 2 + (tuple 4 5) #結果は(2, 3, 2, 3, 4, 5)というArray

「配列 * 整数」は配列の指定回数の繰り返しを作ります。「配列 + 配列」は連結した配列を作ります。

この辺りの事情は外部のスクリプトを呼び出すときでも同じです。例えば次のようなtuple.ps1というファイルを作成します。

# tuple.ps1
$args[0],$args[1]

これを呼び出すには次のようにします。

.\tuple.ps1 2 3 #結果は (2, 3) というArray
.\tuple.ps1 2 3 > result.txt
(.\tuple.ps1 2 3) * 2 + (.\tuple.ps1 4 5) #結果は(2, 3, 2, 3, 4, 5)というArray

重要なのは、こうしてコマンドを実行するとその都度生じた値がパイプラインへ流れるということです。

流す先が実際にどこになるかは呼び出し側によって変わります。コンソール、ファイル、演算子の項、コマンドの引数、変数、などなど。

流したくなければ明示的に破棄する必要があります。

.\tuple.ps1 2 3 > $null
[void](.\tuple.ps1 2 3)
$null = .\tuple.ps1 2 3

このようにすればコマンドを実行して生じた値はどこへも流れず破棄されます。

ちなみに式のトップレベルにある代入演算子は、その結果がパイプラインへ流れません。

$a = "hello" #helloは変数に格納されるのでパイプラインへは流れない

「トップレベル」と断っていると言うことは、トップレベルでなければ流れます。

($a = "hello") # 式のトップレベルはカッコなので代入演算子の結果であるhelloがパイプラインへ流れる。

変数へ代入するたびにいちいち破棄が必要になるのは面倒だからでしょう。意味的にもリダイレクトと同じようにパイプラインの流し先を変数にしただけと考えられます。

この辺りの事情は関数の中でも同じです。

関数というと何か値を返すものと考えますが、PowerShellでももちろんそう考えても良いのですが、返す先は結局はパイプラインなのです。

function compute($filename){
  echo "begin"
  $result = 42 #$result = very_complex_processing $filename の代わり
  echo "end"
  $result
}
compute("example.txt") > result.txt

例えばこのようなcomputeという関数があったとき、result.txtはどのようになるでしょうか。 Rubyあたりをやっていると最後の$result、つまり42だけ出力されそうな気がしてしまいますが、PowerShellでは「begin end 42」が出力されます。

解説をすると次のようになります。

function compute($filename){
  echo "begin" # beginがパイプラインへ流れます。
  $result = 42 # トップレベルにある代入演算子の結果はパイプラインへ流れません。
  echo "end" # endがパイプラインへ流れます。
  $result # $resultの評価結果がパイプラインへ流れます。
}
$r = compute("example.txt") # パイプラインの接続先は変数r。$rは3要素の配列("begin", "end", 42)になります。

この辺りのことが分かっていれば、次の関数もよく理解できるでしょう。

function range($first, $last){
  for($i = $first; $i -le $last; ++$i){
    $i # パイプラインへ$iの値が流れる
  }
}
range 10 15 #結果はArray(10, 11, 12, 13, 14, 15) 10..15と同じ
2017-10-16 ,

PowerShellスクリプトへファイルをドラッグ&ドロップする(bat不要)

ショートカットのリンク先を工夫すればOK。

単純に.ps1へのショートカットを作ってもダメ。.ps1を開く既定のハンドラが登録されていないので。

次のような記事もあるくらいだし、漠然とbatファイル経由でないとダメだと思っていた。

でも次のような記事を見つけて試してみたらうまくいった。

つまり、適当なショートカットを作成して、リンク先を powershell -NoProfile -File ファイル名(.ps1) とすればOK。

色々オプションもあるみたいなので注意。

$Args にちゃんとドロップしたファイルのパスが格納される。空白文字が入っているパスでも大丈夫。UNCでも大丈夫。

考えてみれば当たり前の話なのかもしれないけど、この方法でちゃんとドロップしたファイル名だけが $Args に入るというのはちょっと不思議なような気もする。 -File ファイル名.ps1 の後に適当な文字列を入れて試すとその文字列は $Args[0] に入るのでそういう仕様みたい。

2017-10-15

2017秋の新番組

良い滑り出しかなと思ったのは次:

秋の新番組第一話、最初サクサク切りまくって「今期は楽が出来るかな~」と思っていたのですが後半○を付けたものが多く出ました。

印象 開始日時 チャネル タイトル
10/01(日) 07:00~ テレビ東京 レゴ ニンジャゴー 新シリーズ
× 10/01(日) 25:00~ TOKYO MX お見合い相手は教え子、強気な、問題児
10/01(日) 25:35~ テレビ東京 銀魂 ポロリ篇
10/02(月) 24:00~ TOKYO MX UQ HOLDER!~魔法先生ネギま!2~
× 10/02(月) 25:00~ TOKYO MX ディアホライゾン(被)
× 10/02(月) 25:05~ TOKYO MX aiseki MOGOL GIRL
10/02(月) 25:35~ テレビ東京 おそ松さん 第2期
× 10/03(火) 18:25~ テレビ東京系 ブラッククローバー
10/03(火) 21:54~ TOKYO MX アイドルマスター シンデレラガールズ劇場 第2期
× 10/03(火) 23:00~ TOKYO MX 戦刻ナイトブラッド
10/03(火) 24:30~ TOKYO MX 食戟のソーマ 餐の皿 (第3期)
× 10/03(火) 25:00~ TOKYO MX お酒は夫婦になってから
10/04(水) 17:20~ NHK Eテレ うっかりペネロペ 新シリーズ(第4期)
× 10/04(水) 22:25~ TOKYO MX あめこん!!
× 10/04(水) 22:30~ TOKYO MX TSUKIPRO THE ANIMATION
× 10/04(水) 24:00~ TOKYO MX このはな綺譚
10/05(木) 22:00~ TOKYO MX URAHARA
10/05(木) 23:30~ TOKYO MX Just Because!
× 10/05(木) 24:00~ TOKYO MX 十二大戦
× 10/05(木) 25:58~ TBS DYNAMIC CHORD(ダイナミックコード)
10/06(金) 21:54~ TOKYO MX 大正ちっちゃいさん
× 10/06(金) 22:00~ TOKYO MX ドリフェス! R (2ndシーズン)
10/06(金) 22:30~ TOKYO MX 少女終末旅行
10/06(金) 24:30~ TOKYO MX キノの旅 -the Beautiful World- 新作
× 10/06(金) 25:05~ TOKYO MX Dies irae
10/06(金) 25:23~ テレビ東京 VANISING LINE
10/06(金) 25:40~ TOKYO MX 王様ゲーム The Animation
10/06(金) 25:55~ TBS 結城友奈は勇者である 第2期
× 10/06(金) 26:10~ TOKYO MX グラマラスヒーローズ
× 10/07(土) 06:54~ テレビ東京 シルバニアファミリー ミニストーリー
10/07(土) 09:20~ NHK Eテレ ピングー in ザ・シティ
10/07(土) 09:27~ NHK Eテレ PEANUTS スヌーピー ショートアニメ
10/07(土) 17:30~ 日本テレビ系 タイムボカン 逆襲の三悪人
10/07(土) 17:35~ NHK Eテレ クラシカロイド 第2シリーズ
10/07(土) 22:00~ TOKYO MX 宝石の国
10/07(土) 22:30~ TOKYO MX ラブライブ!サンシャイン!! 第2期
10/07(土) 23:30~ TOKYO MX アイドルマスター SideM
10/07(土) 24:30~ TOKYO MX ブレンド・S
10/07(土) 25:00~ TOKYO MX 鬼灯の冷徹 第弐期
10/07(土) 25:30~ TOKYO MX 魔法使いの嫁
10/08(日) 10:00~ テレビ東京系 カードファイト!! ヴァンガードG Z(第9期)
10/08(日) 22:00~ TOKYO MX アニメガタリズ
10/08(日) 22:30~ TOKYO MX 妹さえいればいい。
10/08(日) 23:00~ TOKYO MX クジラの子らは砂上に歌う
10/08(日) 24:00~ TOKYO MX 干物妹!うまるちゃんR (第2期)
10/08(日) 24:30~ TOKYO MX 血界戦線 & BEYOND (第2期)
10/08(日) 25:35~ TOKYO MX Code:Realize ~創世の姫君~
10/09(月) 24:30~ TOKYO MX つうかあ
× 10/09(月) 25:35~ TOKYO MX おにゃんこポン
10/09(月) 25:40~ TOKYO MX ネト充のススメ
10/09(月) 26:05~ テレビ東京 Wake Up, Girls!新章
10/10(火) 22:05~ AT-X ラブ米(ラブコメ)-WE LOVE RICE- 第2期
10/10(火) 25:41~ TOKYO MX EVIL OR LIVE
10/11(水) 25:05~ TOKYO MX 僕の彼女がマジメ過ぎるしょびっちな件
10/12(木) 24:55~ フジテレビ いぬやしき
10/13(金) 22:30~ WOWOW ROBOMASTERS THE ANIMATED SERIES
10/14(土) 23:00~ NHK Eテレ 3月のライオン 第2シリーズ

これは番組の傾向が偏っていたのか、それとも視聴時の体調の変化によるものなのか不明。