PowerShell with PHP サンプル集

自分用のメモとして。
PowerShellにPHP関数をラッピングさせることで、PowerShellを機能強化してみる。
内容は随時追加予定。

## 事前準備
１．PHPのインストール
※詳細は[「PHPインストールと初期設定(Windows)」](http://www.phpbook.jp/install/)を参照
２．php.exeの格納フォルダを環境変数PATHに登録


## ヘルパー関数

【InvokePHPScript関数（自作関数）】
・PHPスクリプトを実行する
・実行はファイル経由（-rオプションでは実行に失敗するものがあった為）
・後述のサンプルで使う為、宣言しておく必要がある

```ps1:関数定義
filter InvokePHPScript(){
  $tempfile = [System.IO.Path]::GetTempFileName()
  $encoding = [System.Text.Encoding]::GetEncoding("shift_jis")
  ;[System.IO.File]::WriteAllText($tempfile,$_,$encoding)
  php -f $tempfile
  del $tempfile
}
```



## ファイル操作系

【readfile関数】
・ファイルの中身すべてを標準出力に出力する
・参照先はパス、URLの両方指定可能
・php.iniよりphp_openssl.dll（extension）を利用可能にしておく必要がある（サイトによっては、エラーになる為）

```ps1:関数定義
function readfile($filename){
@"
<?php
  readfile('$filename')."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例

readfile 'http://qiita.com/'
# php_openssl.dll利用可の場合
# -> <!DOCTYPE html><html xmlns:og="http://ogp.me/ns#"><head><meta charset="UTF-8" /><title>Qiita - A technical knowledge sharing platform for programmers.</title>...（以下略）

# php_openssl.dll利用不可の場合（サイトによっては失敗する）
# -> PHP Warning:  readfile(http://qiita.com/): failed to open stream: Unable to find the socket transport "ssl" - did you forget to enable it when you configured PHP? ...（以下略）
```


## 配列操作系

【array_diff関数】
ほかの配列と異なる値を持つ要素を取得する

```ps1:関数定義
function array_diff(){
  $str_array = ($args | foreach{'array(' + (($_ | foreach{"'$_'"}) -join ',') + ')'}) -join ','
@"
<?php
  echo join("\n",array_diff($str_array))."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
array_diff ('A','B','C') ('A','C','D')
# -> B
```

【array_intersect関数】
ほかの配列と同じ値を持つ要素を取得する

```ps1:関数定義
function array_intersect(){
  $str_array = ($args | foreach{'array(' + (($_ | foreach{"'$_'"}) -join ',') + ')'}) -join ','
@"
<?php
  echo join("\n",array_intersect($str_array))."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
array_intersect ('A','B','C') ('A','C','D')
# -> A
#    C
```

【natsort関数／natcasesort関数】
・人間が予期する順序で配列をソートする（Natural Sortアルゴリズム）
・natsort関数は大文字・小文字区別あり、natcasesort関数は大文字・小文字区別なし

```ps1:関数定義
function natsort(){
  $str_array = ('array(' + (($input | foreach{"'$_'"}) -join ',') + ')')
  $def_var = '$a = ' + $str_array + ';'
@'
<?php 
'@ + $def_var + @'
  natsort($a);
  echo join("\n",$a)."\n";
?>
'@ | InvokePHPScript
}

function natcasesort(){
  $str_array = ('array(' + (($input | foreach{"'$_'"}) -join ',') + ')')
  $def_var = '$a = ' + $str_array + ';'
@'
<?php 
'@ + $def_var + @'
  natcasesort($a);
  echo join("\n",$a)."\n";
?>
'@ | InvokePHPScript
}
```

```ps1:使用例
('10 Apple','1 Orange','3 Banana','1 apple') | natsort
# -> 1 Orange
#    1 apple
#    3 Banana
#    10 Apple

('10 Apple','1 Orange','3 Banana','1 apple') | natcasesort
# -> 1 apple
#    1 Orange
#    3 Banana
#    10 Apple
```

ちなみに、PowerShellのsort(Sort-Object)では以下の結果となる

```ps1:比較例
('10 Apple','1 Orange','3 Banana','1 apple') | sort
# -> 1 apple
#    1 Orange
#    10 Apple
#    3 Banana
```

## 文字列操作系

【number_format関数】
数値に3桁ごとに","（カンマ）を入れる

```ps1:関数定義
filter number_format($decimals = 0,$dec_point = ".",$thousands_sep = ","){
@"
<?php
  echo number_format('$_',$decimals,'$dec_point','$thousands_sep')."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
'$' + (1000 | number_format 2)
# -> $1,000.00
```

【sscanf関数】
フォーマットされた文字列を配列に格納する

```ps1:関数定義（PowerShell）
filter sscanf($format){
@"
<?php
  echo join("\n",sscanf("$_", "$format"))."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
"2015年11月22日" | sscanf "%d年%d月%d日"
# -> 2015
#    11
#    22
```

【strspn関数】
・指定された文字以外が最初に出現する位置を取得する
・結果の数値は、最初の文字の位置を0としたもの

```ps1:関数定義
filter strspn($mask){
@"
<?php
  echo strspn('$_','$mask')."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
"0923 abc" | strspn "0123456789"
# -> 4

"abc 0923" | strspn "0123456789"
# -> 0
```


【strcspn関数】
・指定された文字が最初に出現する位置を取得する
・結果の数値は、最初の文字の位置を0としたもの

```ps1:関数定義
filter strcspn($mask){
@"
<?php
  echo strcspn('$_','$mask')."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
"0923 abc" | strcspn "0123456789"
# -> 0

"abc 0923" | strcspn "0123456789"
# -> 4
```

【strtr関数】
文字列を一括置換する

```ps1:関数定義
filter strtr($replace_pairs){
  $str_replace_pairs = `
    if(($replace_pairs | foreach{$_.GetType().Name}).Contains('Object[]')){
      ($replace_pairs | foreach{($_ | foreach{"'$_'"}) -join '=>'}) -join ','
    } else {
      ($replace_pairs | foreach{"'$_'"}) -join '=>'
    }
@"
<?php
  echo strtr('$_', array($str_replace_pairs))."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
'(^_^)' | strtr ('^','+')
# -> (+_+)

'(^_^)' | strtr ('^','/'),('_','/')
# -> (///)
```

【substr_replace関数】
文字列中の特定範囲内の文字列を置換する

```ps1:関数定義
filter substr_replace($replacement,$start,$length = 0){
  if($length -eq 0){
@"
<?php
  echo substr_replace('$_', '$replacement', $start)."\n";
?>
"@ | InvokePHPScript
} else {
@"
<?php
  echo substr_replace('$_', '$replacement', $start, $length)."\n";
?>
"@ | InvokePHPScript
  }
}
```

```ps1:使用例
'0000000000' | substr_replace '1' 2 1
# -> 0010000000
```

【ucfirst関数】
文字列の最初の文字を大文字にする

```ps1:関数定義
filter ucfirst(){
@"
<?php
  echo ucfirst('$_')."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
'how are you?' | ucfirst
# -> How are you?
```

【ucwords関数】
単語の最初の文字を大文字にする

```ps1:関数定義
filter ucwords(){
@"
<?php
  echo ucwords('$_')."\n";
?>
"@ | InvokePHPScript
}
```

```ps1:使用例
'who am i?' | ucwords
# -> Who Am I?
```


## データベース系（SQLite3）
php.iniよりphp_sqlite3.dll（extension）を利用可能にしておく必要がある

【exec関数】
更新系のSQLを実行する

```ps1:関数定義
filter sqlite3_exec($path){
  '<?php' + "`n" + `
  '$db = new SQLite3(' + "'$path'" + ');' + "`n" + `
  '$db->exec(' + "'$_'" + ');' + "`n" + `
  '?>' | InvokePHPScript
}
```

```ps1:使用例
'create table test(id integer,name string);' | sqlite3_exec 'test.db'
'insert into test values(1,"太郎");' | sqlite3_exec 'test.db'
'insert into test values(2,"花子");' | sqlite3_exec 'test.db'
'insert into test values(10,"ジョン");' | sqlite3_exec 'test.db'
```

【query関数】
参照系のSQLを実行する

```ps1:関数定義
filter sqlite3_query($path,$delimiter = ','){
  '<?php' + "`n" + `
  '$db = new SQLite3(' + "'$path'" + ');' + "`n" + `
  '$result = $db->query(' + "'$_'" + ');' + "`n" + `
  'while($row = $result->fetchArray(SQLITE3_ASSOC)){' + "`n" + `
  '  echo join("' + $delimiter + '",$row)."\n";' + "`n" + `
  '}' + "`n" + `
  '?>' | InvokePHPScript
}
```

```ps1:使用例
'select * from test where id < 10;' | sqlite3_query 'test.db'
# -> 1,太郎
#    2,花子

'select * from test where id < 10;' | sqlite3_query 'test.db' "\t"
# -> 1       太郎
#    2       花子
```