PowerShell - 正規表現
match演算子
変数$Matchesでマッチした文字列を取得できる。要素0がマッチした文字列、要素1以降が部分マッチ(キャプチャ)された文字列になる。
ただし最初にマッチしたものしか得られないみたい。
PS C:\> "abcde" -match "(.)(.)" True PS C:\> $Matches Name Value ---- ----- 2 b 1 a 0 ab PS C:\> $Matches[0] ab
配列からマッチした要素を抜き出すこともできる様です。
PS C:\> @("one", "two", "three", "four", "five") -match "t" two three
regexオブジェクト
正規表現オブジェクトを使用するとマッチした全てが取得できる。
PS C:\> $re = New-Object regex("(.)(.)") # $re = [regex]"(.)(.)"でも可 PS C:\> $m = $re.Matches("abcde") PS C:\> $m Groups : {ab, a, b} Success : True Captures : {ab} Index : 0 Length : 2 Value : ab Groups : {cd, c, d} Success : True Captures : {cd} Index : 2 Length : 2 Value : cd PS C:\> $m[1].Groups[1] Success : True Captures : {c} Index : 2 Length : 1 Value : c PS C:\> $m[1].Groups[1].Value c
後方参照
PS C:\> $re = new-object regex( "(\d)(\d)(\d)(\d)" ) PS C:\> $re.replace("1234", "`$4`$3`$2`$1") 4321
PowerShell - 制御構造(条件分岐)
if
if(条件){ 文 } elseif(条件){ 文 } else { 文 }
switch
switch($v){ 1 {文; break} 2 {文; break} ($_ -ge 3) {文; break} default {文; break} } # 正規表現 (-matchでないことに注意) $s = "abcd" switch -Regex($s){ "^a" {Write-Host 1;break} # aで始まる "bc" {Write-Host 2;break} # bcを含む default {Write-Host 3;break} } # ワイルドカード (-likeでないことに注意) switch -Wildcard($s){ "a*" {Write-Host 1;break} # aで始まる "bc" {Write-Host 2;break} # bcを含む default {Write-Host 3;break} }
PowerShell - 制御構造(ループ)
for
for($i = 0; $i -lt 5; $i++){ Write-Host $i } 0 1 2 3 4
foreach
foreach($i in (0..4)){ Write-Host $i } 0 1 2 3 4
while / do while
$i = 0 while($i -lt 5){ Write-Host $i $i++ } 0 1 2 3 4 $i = 0 do { Write-Host $i $i++ }while($i -lt 5) 0 1 2 3 4
break/continue
for($i = 0; $i -lt 10; $i++){ if($j -eq 2){break} Write-Host $i } 0 1 for($i = 0; $i -lt 10; $i++){ if($i -eq 2){continue} Write-Host $i } 0 1 3 4 5 6 7 8 9
多重ループからの脱出
Write-Host "before loop" :exit_all for($i = 0; $i -lt 10; $i++){ for($j = 0; $j -lt 10; $j++){ Write-Host $i, $j if($j -eq 2){break exit_all} } } Write-Host "after loop" before loop 0 0 0 1 0 2 after loop
ラベルをforループの下に移動したら、"after loop"が非表示になった。
ラベルが付いている文の次へジャンプするということ?
PowerShell - データと変数の型
文字と数値が混ざった式は、左の型に合わせる? でにキャスト?すれば変換できるっぽい
PS C:\> 1 + "1" 2 PS C:\> "1" + 1 11 PS C:\> [long]"1" + 1 2
変数の型
最初に使用するときに型の宣言をすれば、その型の変数になる。
使用をやめるときはRemove-Variable "$を付けないの変数名"
PS C:\> [long]$i = 1 PS C:\> $i = "abc" 値 "abc" を型 "System.Int64" に変換できません。エラー: "入力文字列の形式が正しくありません。" 発生場所 行:1 文字:1 + $i = "abc" + ~~~~~~~~~~ + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException + FullyQualifiedErrorId : RuntimeException PS C:\> Remove-Variable i PS C:\> $i = "abc" PS C:\> $i abc
短縮形が登録されている型と正式型(Ver. 5.1の場合)
PowerShell - ファイル/フォルダリストの取得
バージョン 5.1
PS C:\> Get-ChildItem -File PS C:\>Get-ChildItem -Directory
バージョン 2.0
PSIsContainerプロパティ?がTrueならフォルダ、FalseならファイルなのでWhere-Objectで抽出する。
バージョン5.1でも使用可能。
PS C:\> Get-ChildItem | Where-Object{!$_.PSIsContainer} # ファイル PS C:\> Get-ChildItem | Where-Object{$_.PSIsContainer} # フォルダ
PowerShell - テキストファイルの読み書き
書き込みはOut-Fileを使用する。文字列はパイプで渡すか、-InputObjectでオブジェクトを渡す。-Appendで追加書き込み。
読み込みはGet-Contentを使用する。各行毎の文字列の配列として変数に読み込まれる。ただし1行のみのファイルはStringになるため、GetType()のNameプロパティで確認が必要となる。
$file = ".\test.txt" # ファイルへの書き込み "1行目” | Out-File $file -Encoding default "2行目” | Out-File $file -Encoding default -Append # 追加書込モード Out-File $file -Encoding default -Append -InputObject "3行目” # ファイル読み込み(複数行) $txt = Get-Content $file $txt $txt.GetType() # IsPublic IsSerial Name BaseType # -------- -------- ---- -------- # True True Object[] System.Array $txt[1] # 2行目 # ファイル読み込み(1行) $txt = Get-Content $file $txt.GetType() #IsPublic IsSerial Name BaseType #-------- -------- ---- -------- #True True String System.Object
1行ずつの読み取り
.NETのStreamReaderを使用する。
StreamReaderは、System.IO.StreamReaderなのだけれども、Systemは省略できるっぽいです。ReadLineメソッドで1行ずつ読みとる動作を$nullになるまで繰り返す。
$path = Get-Location $file = "test.txt" $enc = [Text.Encoding]::Default # Shift_JIS $reader = New-Object IO.StreamReader(($path.Path + "\" + $file), $enc) while ( ($line = $reader.ReadLine()) -ne $null){ Write-Host $line } $reader.close()
PowerShell - 配列
代入
PS C:\> $ary = 1,2,3,4,5 PS C:\> $ary = 1 .. 5 PS C:\> $ary = @() #空配列 PS C:\> $ary = @(1,2,3,4,5) PS C:\> $ary = "abcdefg" -split "" # 1文字ずつに分割(前後に空文字の要素が入る) PS C:\> $ary = "abcdefg" -split "\B" # 1文字ずつに分割(前後に空文字の要素が入らない)
要素アクセス
PS C:\> $a = 1..5 PS C:\> $a[2] = 300 PS C:\> $a 1 2 300 4 5 PS C:\> $a[0] 1 PS C:\> $a[0,2,4] 1 300 5 PS C:\> $a[0..3] 1 2 300 4 PS C:\> $a[4..0] # 逆順に並べ替え 5 4 300 2 1
要素追加
PS C:\> $a = 1..5 PS C:\> $a += 100 # 末尾に追加 PS C:\> $a 1 2 3 4 5 100 PS C:\> $a = @(-100) + $a # 先頭に追加 PS C:\> $a -100 1 2 3 4 5 100
配列のコピー
PS C:\> $a = 0..4 PS C:\> $b = $a # $bは$aと同じオブジェクトへの参照 PS C:\> $a[0] = 100 PS C:\> $b 100 1 2 3 4 PS C:\> $a.GetHashCode() 28959488 PS C:\> $b.GetHashCode() 28959488 PS C:\> $a = 0..4 PS C:\> $b = $a.Clone() # 別オブジェクトとしてコピー PS C:\> $a[0] = 100 PS C:\> $b 0 1 2 3 4 PS C:\> $a.GetHashCode() 38658037 PS C:\> $b.GetHashCode() 45724662
その他
PS C:\> $a.Count # 要素数 7 PS C:\> $a.Contains(-100) # 要素に存在するか True PS C:\> -100 -in $a # 要素に存在するか(V3以降) True