[PowerShell] たまに書くワンライナー


PowerShellにはがあり、配列、連想配列、オブジェクト等を扱えます。パイプライン処理もできます。これを生かして手元で何かごちゃごちゃすると便利なのですが、普段使わないので忘れがちです。それを書き留めます。そして忘れます。

基礎

パイプライン処理ではforeach, where, select, sortなどのコマンドをよく使う。
渡されたデータの各要素に$_でアクセスできる。
%foreachを、?whereを意味するエイリアス。ややこしいので気をつけて使う。

(例)where でフィルター、foreachで加工、改行せずにコンソール出力
@(1..10) | where {$_ % 2 -eq 0} | foreach {"${_} "} | Write-Host -NoNewline
# 2 4 6 8 10 

ファイル名の変更

カレントディレクトリの全ファイルの拡張子を.txtにする
ls | foreach {ren $_ ($_.BaseName + ".txt")}
.logファイルの拡張子を.txtにする
ls | ?{$_.Extension -eq ".log"} | %{ren $_ ($_.BaseName + ".txt")}

文字列を扱う

ファイルから空行を消す
cat sparse.txt | where {$_ -ne ""} > dense.txt
# sparse.txt の空行を消したものを dense.txt として出力
(数値型変数の展開)
$n = 10

echo ("$n + 1 = " + ($n+1))
# 10 + 1 = 11

echo(      $n + 1 )
# 11
echo("" + ($n + 1))
# 11
echo("" +  $n + 1 )
# 101

echo("${n}yen")
# 10yen
echo('${n}yen')
# ${n}yen

日付時刻

(Get-Dateを使う)
(Get-Date).GetType().Fullname
# System.DataTime という型

(Get-Date).AddHours(-1)
# 1時間前のDataTimeが得られる
1時間以内に作成されたファイルを表示
ls | where {(Get-Date).AddHours(-1) -le $_.CreationTime}
1時間以前に作成されたファイルを全消去(危ない)
ls | where {$_.CreationTime -le (Get-Date).AddHours(-1)} | rm

連番で何かする

@(n..m)で配列を作ってパイプで渡す。(n..m)とも書ける。

CSVを作成(列名なし)
@(1..10000) | foreach {"${_},user_${_}"} > foo.csv
生成されるデータ
1,user_1
2,user_2 ...
値にダブルクォーテーションを含めたい場合
@(1..10000) | foreach{"$_" + ',"user ' + $_ + 'is here"'} > foo.csv
生成されるデータ
1,"user 1 is here"
2,"user 2 is here" ...
  • ""で括らないと変数が展開されないので先頭は"$_"
  • ダブルクォーテーションは''の中に書いた方が分かりやすい
  • 真ん中にある$_""で括る必要はない
    • (前方の文字列と+しているので文字列と解釈される)

補足

文法をおさらい

  • 変数の先頭に$が付く
  • |でパイプ(次のコマンドに向けて出力)して、>とか>>でファイルに出力
  • $_でパイプで送られてきたデータの各要素を参照
  • "で囲むと$n ${n}という表記で、文字列中で変数を参照できる
  • 'で囲むと変数を展開しない
  • {}で囲まれた処理を「スクリプトブロック」と言う
  • ()でコマンドを囲むと結果をオブジェクトとして扱える
  • []で配列やオブジェクトの各要素にアクセスする
    • (ls)[0] でカレントディレクトリのファイル1つを対象に取れる

これマジ?

"a" + 1 👈 😉「a1」
1 + "a" 👈 🤬「値”a”を型"System.Int32"に変換できません。」
"" + 1 + "a" 👈 😌「1a」)

@(1..10) 👈 😉「1, 2, ... 10」
@(1...10) 👈 😤「1, 0」(.100.1と解釈されて、丸めて0
@(1...50) 👈 🤔「1, 0」
@(1...51) 👈 🤔「1」

@(1...50000000000000005) 👈 🤯「1, 0」
@(1...50000000000000006) 👈 😇「1」(環境に依存しそう)

ビル・ゲイツ!!!