PowerShell

#23
TIOBE#44
PYPL#18
GitHub#23
RedMonk#18
プログラミング言語スクリプト言語システム管理自動化Microsoftクロスプラットフォーム

プログラミング言語

PowerShell

概要

PowerShellは、Microsoft社が開発したオブジェクト指向ベースのコマンドライン・スクリプト言語です。

詳細

PowerShellは2006年にMicrosoft社のJeffrey Snover氏によって開発されたタスクベースのコマンドライン・シェルおよびスクリプト言語で、.NET Frameworkを基盤として構築されています。従来のテキストベースのシェルとは異なり、.NETオブジェクトを直接操作できることが最大の特徴です。Windows PowerShellからPowerShell Core(現在はPowerShell 7+)への進化により、Windows、Linux、macOSでの動作が可能になり、クロスプラットフォーム対応を実現しました。システム管理、自動化、DevOps、クラウド管理などの分野で広く活用されており、豊富なコマンドレット(cmdlet)と強力なパイプライン機能を提供します。

書き方の例

Hello World

# 基本的な出力
Write-Host "Hello, World!"

# 変数を使った出力
$message = "こんにちは、PowerShell!"
Write-Host $message

# フォーマット出力
$name = "太郎"
$age = 25
Write-Host "私の名前は$nameで、$age歳です。"

# 配列の出力
$fruits = @("りんご", "バナナ", "オレンジ")
Write-Host "果物: $($fruits -join ', ')"

# 複数の出力方法
"シンプルな文字列出力"
Write-Output "パイプラインに送信"
Write-Information "情報メッセージ" -InformationAction Continue

変数とデータ型

# スカラー変数
$number = 42
$float = 3.14
$string = "文字列"
$boolean = $true

# 配列
$fruits = @("りんご", "バナナ", "オレンジ")
$numbers = @(1, 2, 3, 4, 5)
$mixed = @("文字列", 42, $true)

# ハッシュテーブル(連想配列)
$person = @{
    Name = "田中太郎"
    Age = 30
    City = "東京"
}

# 厳密な型指定
[int]$integerVar = 100
[string]$stringVar = "型指定された文字列"
[datetime]$dateVar = Get-Date

# 配列の特殊な作成方法
$range = 1..10           # 1から10までの連続数値
$letters = 'A'..'Z'      # AからZまでの文字

Write-Host "数値: $number"
Write-Host "配列の要素数: $($fruits.Count)"
Write-Host "ハッシュテーブルの値: $($person.Name)"
Write-Host "型情報: $($number.GetType().Name)"

条件分岐

# 基本的なif文
$score = 85
$grade = ""

if ($score -ge 90) {
    $grade = "A"
} elseif ($score -ge 80) {
    $grade = "B"
} elseif ($score -ge 70) {
    $grade = "C"
} else {
    $grade = "D"
}

Write-Host "得点: $score, 評価: $grade"

# 複数条件の組み合わせ
$age = 20
$hasLicense = $true

if ($age -ge 18 -and $hasLicense) {
    Write-Host "運転できます"
} elseif ($age -ge 18) {
    Write-Host "免許を取得してください"
} else {
    Write-Host "18歳になってから免許を取得してください"
}

# switch文
$day = "水曜日"
switch ($day) {
    "月曜日" { Write-Host "週の始まり" }
    "水曜日" { Write-Host "週の中間" }
    "金曜日" { Write-Host "週末まであと少し" }
    default { Write-Host "他の曜日" }
}

# 比較演算子の例
$value = 10
if ($value -eq 10) { "等しい" }
if ($value -ne 5) { "等しくない" }
if ($value -gt 5) { "より大きい" }
if ($value -lt 20) { "より小さい" }
if ("Hello" -like "He*") { "パターンマッチ" }
if ("[email protected]" -match "\w+@\w+\.\w+") { "正規表現マッチ" }

配列とハッシュテーブルの操作

# 配列の操作
$fruits = @("りんご", "バナナ", "オレンジ")

# 要素の追加
$fruits += "ぶどう"
$fruits = $fruits + @("いちご", "メロン")

# 配列の要素にアクセス
Write-Host "最初の果物: $($fruits[0])"
Write-Host "最後の果物: $($fruits[-1])"
Write-Host "最初の3つ: $($fruits[0..2] -join ', ')"

# 配列の操作メソッド
$fruits | ForEach-Object { Write-Host "果物: $_" }
$longFruits = $fruits | Where-Object { $_.Length -gt 3 }
Write-Host "3文字より長い果物: $($longFruits -join ', ')"

# ハッシュテーブルの操作
$person = @{
    Name = "田中太郎"
    Age = 30
    City = "東京"
}

# 新しいキーと値の追加
$person.Job = "エンジニア"
$person["Hobby"] = "読書"

# キーの存在確認
if ($person.ContainsKey("Age")) {
    Write-Host "年齢: $($person.Age)"
}

# すべてのキーと値を取得
foreach ($key in $person.Keys) {
    Write-Host "$key : $($person[$key])"
}

# ハッシュテーブルから配列への変換
$keys = $person.Keys
$values = $person.Values
Write-Host "キー: $($keys -join ', ')"

ループ処理

# ForEach-Object(パイプライン)
1..5 | ForEach-Object {
    Write-Host "$_ の2乗は $($_ * $_) です"
}

# for文
for ($i = 1; $i -le 5; $i++) {
    Write-Host "$i の2乗は $($i * $i) です"
}

# foreach文
$numbers = @(1, 2, 3, 4, 5)
foreach ($num in $numbers) {
    $double = $num * 2
    Write-Host "数値: $num, 2倍: $double"
}

# while文
$count = 0
while ($count -lt 5) {
    Write-Host "カウント: $count"
    $count++
}

# do-while文
$counter = 0
do {
    $counter++
    Write-Host "実行回数: $counter"
} while ($counter -lt 3)

# 配列のループ(インデックス付き)
for ($i = 0; $i -lt $fruits.Count; $i++) {
    Write-Host "インデックス $i : $($fruits[$i])"
}

関数の定義と呼び出し

# 基本的な関数
function Get-Greeting {
    param([string]$Name)
    return "こんにちは、$Name さん!"
}

# パラメータのデフォルト値
function Get-Area {
    param(
        [int]$Width,
        [int]$Height = 10
    )
    return $Width * $Height
}

# 複数の値を返す関数
function Get-NameAge {
    return @("田中太郎", 25)
}

# 高度なパラメータ定義
function Get-ProcessInfo {
    param(
        [Parameter(Mandatory=$true)]
        [string]$ProcessName,
        
        [Parameter()]
        [switch]$IncludeModules,
        
        [Parameter()]
        [ValidateSet("Name", "Id", "CPU")]
        [string]$SortBy = "Name"
    )
    
    $processes = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
    
    if ($IncludeModules) {
        return $processes | Select-Object Name, Id, Modules
    } else {
        return $processes | Select-Object Name, Id, CPU | Sort-Object $SortBy
    }
}

# 関数の呼び出し
$message = Get-Greeting -Name "山田"
Write-Host $message

$area = Get-Area -Width 5  # Heightはデフォルト値を使用
Write-Host "面積: $area"

$name, $age = Get-NameAge
Write-Host "名前: $name, 年齢: $age"

オブジェクト指向とクラス

# クラスの定義(PowerShell 5.0以降)
class Car {
    [string]$Make
    [string]$Model
    [int]$Year
    [int]$Mileage = 0
    
    # コンストラクタ
    Car([string]$make, [string]$model, [int]$year) {
        $this.Make = $make
        $this.Model = $model
        $this.Year = $year
    }
    
    # メソッド
    [void]Drive([int]$distance) {
        $this.Mileage += $distance
        Write-Host "$distance km 運転しました。総走行距離: $($this.Mileage) km"
    }
    
    [string]GetInfo() {
        return "$($this.Year)年式 $($this.Make) $($this.Model)"
    }
    
    # 静的メソッド
    static [string]GetCarCount() {
        return "車の総数を取得する機能"
    }
}

# オブジェクトの作成と使用
$myCar = [Car]::new("トヨタ", "プリウス", 2022)
Write-Host $myCar.GetInfo()
$myCar.Drive(50)
$myCar.Drive(30)

# カスタムオブジェクトの作成(PSCustomObject)
$customPerson = [PSCustomObject]@{
    Name = "山田花子"
    Age = 28
    Department = "開発部"
}

$customPerson | Add-Member -MemberType ScriptMethod -Name "GetDescription" -Value {
    return "名前: $($this.Name), 年齢: $($this.Age), 部署: $($this.Department)"
}

Write-Host $customPerson.GetDescription()

ファイル操作とテキスト処理

# ファイルの作成と書き込み
$content = @"
これはテストファイルです。
PowerShellでファイル操作を学んでいます。
複数行のテキストを書き込めます。
"@

$content | Out-File -FilePath "sample.txt" -Encoding UTF8

# ファイルの読み込み
$fileContent = Get-Content -Path "sample.txt" -Encoding UTF8
foreach ($line in $fileContent) {
    Write-Host "読み込み: $line"
}

# CSV形式のデータ処理
$csvData = @"
Name,Age,Job
田中太郎,30,エンジニア
山田花子,25,デザイナー
佐藤次郎,35,マネージャー
"@

$csvData | Out-File -FilePath "employees.csv" -Encoding UTF8

# CSVファイルの読み込みとオブジェクト化
$employees = Import-Csv -Path "employees.csv" -Encoding UTF8

foreach ($employee in $employees) {
    Write-Host "名前: $($employee.Name), 年齢: $($employee.Age), 職業: $($employee.Job)"
}

# ファイルシステムの操作
$files = Get-ChildItem -Path "." -Filter "*.txt"
foreach ($file in $files) {
    Write-Host "ファイル: $($file.Name), サイズ: $($file.Length) bytes"
}

# JSONデータの処理
$jsonData = @{
    Name = "API Response"
    Data = @(
        @{Id = 1; Title = "項目1"},
        @{Id = 2; Title = "項目2"}
    )
    Status = "Success"
}

$jsonString = $jsonData | ConvertTo-Json -Depth 3
Write-Host "JSON形式:"
Write-Host $jsonString

$parsedJson = $jsonString | ConvertFrom-Json
Write-Host "パース後: $($parsedJson.Name)"

システム管理とコマンドレット

# プロセス管理
$processes = Get-Process | Where-Object { $_.CPU -gt 10 } | 
             Sort-Object CPU -Descending | 
             Select-Object -First 5 Name, CPU, WorkingSet

Write-Host "CPU使用率の高いプロセス TOP 5:"
$processes | Format-Table -AutoSize

# サービス管理
$services = Get-Service | Where-Object { $_.Status -eq "Running" } |
            Sort-Object Name |
            Select-Object Name, Status, StartType

Write-Host "実行中のサービス数: $($services.Count)"

# ネットワーク情報
$networkAdapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" }
foreach ($adapter in $networkAdapters) {
    Write-Host "アダプター: $($adapter.Name), 速度: $($adapter.LinkSpeed)"
}

# イベントログの確認
$recentErrors = Get-EventLog -LogName System -EntryType Error -Newest 5 -ErrorAction SilentlyContinue
if ($recentErrors) {
    Write-Host "最近のシステムエラー:"
    $recentErrors | Select-Object TimeGenerated, Source, Message | Format-Table -Wrap
}

# レジストリ操作
$regValue = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name "ProductName" -ErrorAction SilentlyContinue
if ($regValue) {
    Write-Host "Windows版: $($regValue.ProductName)"
}

特徴的な機能

パイプラインとフィルタリング

# 強力なパイプライン処理
Get-Process | 
    Where-Object { $_.ProcessName -like "chrome*" } |
    Sort-Object WorkingSet -Descending |
    Select-Object ProcessName, Id, @{Name="Memory(MB)"; Expression={[math]::Round($_.WorkingSet/1MB, 2)}} |
    Format-Table -AutoSize

# 配列のフィルタリングと変換
$numbers = 1..20
$evenSquares = $numbers | 
    Where-Object { $_ % 2 -eq 0 } |
    ForEach-Object { $_ * $_ }

Write-Host "偶数の2乗: $($evenSquares -join ', ')"

# グループ化と集計
$files = Get-ChildItem -Path "C:\Windows\System32" -File -ErrorAction SilentlyContinue
$filesByExtension = $files | 
    Group-Object Extension |
    Sort-Object Count -Descending |
    Select-Object Name, Count

Write-Host "拡張子別ファイル数:"
$filesByExtension | Format-Table -AutoSize

エラーハンドリング

# try-catch-finally
try {
    $result = 10 / 0
    Write-Host "結果: $result"
}
catch [System.DivideByZeroException] {
    Write-Error "ゼロで割ろうとしました: $($_.Exception.Message)"
}
catch {
    Write-Error "予期しないエラー: $($_.Exception.Message)"
}
finally {
    Write-Host "処理を完了しました"
}

# エラーアクション設定
Get-Process -Name "NonExistentProcess" -ErrorAction SilentlyContinue
if (-not $?) {
    Write-Host "プロセスが見つかりませんでした"
}

# カスタムエラーの生成
function Test-Value {
    param([int]$Value)
    
    if ($Value -lt 0) {
        throw [System.ArgumentException]::new("値は0以上である必要があります")
    }
    
    return $Value * 2
}

並行処理とジョブ

# バックグラウンドジョブ
$job1 = Start-Job -ScriptBlock { Start-Sleep 5; Get-Date }
$job2 = Start-Job -ScriptBlock { Start-Sleep 3; Get-Process | Measure-Object }

Write-Host "ジョブを実行中..."
Wait-Job $job1, $job2

$result1 = Receive-Job $job1
$result2 = Receive-Job $job2

Write-Host "ジョブ1結果: $result1"
Write-Host "ジョブ2結果: プロセス数 $($result2.Count)"

Remove-Job $job1, $job2

# 並列処理(PowerShell 7+)
$servers = @("server1", "server2", "server3")
$servers | ForEach-Object -Parallel {
    # 仮想的なサーバー応答確認
    Start-Sleep (Get-Random -Minimum 1 -Maximum 3)
    Write-Output "$_ : 応答OK"
} -ThrottleLimit 3

バージョン

バージョン ステータス 主要な特徴 リリース年
PowerShell 7.4 Latest 改善されたパフォーマンス 2023
PowerShell 7.3 Current $PSStyle、クラス改善 2022
PowerShell 7.2 LTS クロスプラットフォーム安定化 2021
PowerShell 7.1 Current 実験的機能、PSReadLine改善 2020
PowerShell 7.0 Major .NET Core移行、Linux/macOS対応 2020
Windows PowerShell 5.1 Legacy Windows標準、クラスサポート 2016

参考ページ

公式ドキュメント

学習リソース

開発ツール