結論
以下の関数をpowershell profileに登録すると、あたかもLinuxのbase64コマンドのようになります
function base64(){
Param([switch]$encode=$true, [switch]$decode=$false, [Parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$input)
Begin{}
Process{
if($decode){
$byte = [System.Convert]::FromBase64String($input)
$txt = [System.Text.Encoding]::Default.GetString($byte)
echo $txt
}
elseif($encode){
$byte = ([System.Text.Encoding]::Default).GetBytes($input)
$b64enc = [Convert]::ToBase64String($byte)
echo $b64enc
}
}
End{}
}
使い方
# encodeオプションは省略可
echo "text here" | base64 -encode
# -> "dGV4dCBoZXJl"
echo "dGV4dCBoZXJl" | base64 -decode
# -> "text here"
# 複数の入力も可
echo "text here", "sample text" | base64 -encode
# -> "dGV4dCBoZXJl"
# -> "c2FtcGxlIHRleHQ="
echo "dGV4dCBoZXJl", "c2FtcGxlIHRleHQ=" | base64 -decode
# -> "text here"
# -> "sample text"
イントロ
WebサービスでAPIを使用する際やKubernetesの設定などで、Base64でエンコードされた文字列をデコードしたい場面がちょくちょくあります
Linuxの場合、以下のようにパイプラインをつないで一発でデコードできるのですが、Windowsの場合これが一発でできないので非常に不便でした
echo "dGV4dCBoZXJl" | base64 --decode
そこでWindows Powershellのプロファイルに関数を作って疑似的に作ってやろうというのが今回の試みです
提供した関数ではオプションのハイフンの数が1個少ないので、ハイフン1個の時は省略形というこだわりがある方は好みで引数名を変更してください
関数の解説
関数の名前が疑似的なコマンドとなるので、今回はbase64という名前の関数を作ります
Process部分
エンコード、デコード機能としての肝となる部分はProcess
ブロック内にあります
decodeオプションがついていればif($decode)
内のブロックが、
encodeオプションがついていればelseif($encode)
内のブロックが実行されます
実行内容については以下のページのコードを用いています
PowerShellでBase64のエンコードとデコード
Param部分
本来のbase64は encode
,decode
のオプションがあり、引数としてエンコード/デコードするテキストが入ります
今回これを疑似的に再現するにあたって、オプション含めてすべてpowershell関数の引数(パラメータ)として扱います
具体的なオプションの扱い方
powershellでは引数の型を指定でき、[switch]
というのはbool
型を意味します
powershellでこのbool
型の引数をトリガーするには-引数名
という形になるため、Linuxのオプションのような表記になります
つまり、[switch]$encode=$true
はデフォルトでtrue
のencode
という名前の引数をとる、ということを定義しています
パイプラインからの入力を受け取る引数の指定
[string]$input
だけを定義して終わってしまうと、実はパイプラインからの入力を引数として受け取らないという問題が発生します
そこで[Parameter(ValueFromPipeline=$true)]
を追加することで、パイプラインからの入力を受け付けるようにします
あとは必須の引数であることを宣言するため、Mandatory=$true
を追加しています
複数の入力に対応
Process
ブロックの中身がそのまま記載された関数を作ってしまうと、最初の1つのみがパイプラインからの入力として認識されてしまいます
Begin
ブロック、Process
ブロック、End
ブロックの3つで構成することにより、パイプラインから複数の入力が受け取れるようになります
参考: PowerShell: Creating Functions that accept Pipeline Input (ByValue)