「バッチファイルからPowerScriptに乗り換える際のまとめ」サイトが、非常に助けになります。
PowerShell7
バージョン確認方法
$PSVersionTable
# コメント
’’ #シングルクォーテーションの中は文字列として処理されます。変数は、展開されません。
$a='太郎’
$b='こんにちは、$aです'
$b
こんにちは、$aです
”” #ダブルクォーテーションの中は文字列として処理されます。変数は、展開され変数の代入されている値が表示されます。
$a="太郎"
$b="こんにちは、$aです"
$b
こんにちは、太郎です
$args[0]~$args[8]
注意する点は、%0にあたる部分自分自身のファイルパスは、引数配列には入らないということ。
バッチの%1と同じ位置の引数が、$args[0]になる
$MyInvocation.MyCommand.Path
$PSScriptRoot
または、
$myPath = Split-Path -Parent $MyInvocation.MyCommand.Path
環境変数なら
$env:環境変数=値
通常の変数なら
$変数名=値
パス名を取得
$myPath = $PSScriptRoot
$myPath = Split-Path -Parent $MyInvocation.MyCommand.Path
ファイル名を取得
$filename = Split-Path -Leafbase $MyInvocation.MyCommand.Path
説明
$MyInvocation.MyCommand.Path :自分自身のフルパス名を取得する(ファイル名含む絶対アドレス)
Split-Path :リファレンス(指定されたパス部分を返す)
-LeafBase #ファイル名(拡張子なし)
-Leaf #ファイル名(拡張子あり)
-Parent #親ディレクトリ(このステートメントに与えたパスの親ディレクトリを取得)
-Path #ディレクトリ(ファイル名を含まない)
-Extension #拡張子のみ
-NoQualifier #ドライブ名を含まないディレクトリ
-Qualifier #ドライブ名のみ
Get-Date #yyyy年M月dd日 hh:mm:ss
バッチの場合、ファイルの読み込みは基本for文で読み込みました。
Powershellの場合、Get-Contentsでの読み込みが多いと思います。このコマンドレットは、バッチのTYPEに近いですが、Powershellの場合、ファイルのデータを読み込んでパイプラインを使用して次の処理に渡すといった作法が多くなります。(Linuxなどのシェルでよく使用するcat "ファイル名" | awk~みたいな感じです)
実は、このGet-Contentsのエイリアスとしてcatが設定されていますのでLinuxのシェルの利用方法を意識したのだと思います。
Get-Contents "ディレクトリ名\ファイル名" -encodeing oem #Shift-JISの場合のエンコード
cat "ディレクトリ名\ファイル名" -encodeing oem #cat エイリアス Shift-JISの場合のエンコード
gc "ディレクトリ名\ファイル名" -encodeing oem #gc エイリアス Shift-JISの場合のエンコード
Out-File -Append $FilePath
例:現在日時をファイルに追記する
Get-Date | Out-File -Append $FilePath
Out-File $FilePath
例:現在日時をファイルに追記する
Get-Date | Out-File $FilePath
Out-File $FilePath
#追記のオプション
-Append
#文字コードを指定
-Encording oem # windows上では、S-JIS
-Encording utf-8 # utf-8 BOMなし
#パスを結合して作る \の入り方を正しく行うことができる
Join-Path Join-Path -Path "元のパス" -ChildPath "追加したいパス"
#必要な部分を分割して抽出する
Split-Path Split-Path -Path "分割する対象のパス"
#パスの変換を行う
Convert-Path Convert-Path ~ #現在のホーム ディレクトリへのパスを文字列に変換
#パスのすべての要素が存在するかを知らべ、ブール値を返す
Test-Path Test-Path -Path "テストするパス"
.Substring(開始文字,(文字数))
※文字数未記入で最後までになる
$string.substring(開始文字,(文字数))
※開始文字は0から数える
$STR="abcdefg"
$A=$STR.Substring(0,2)
$B=$STR.Substring(2,3)
echo $A $B
ab
cde
IndexOf(検索文字,(開始位置)) :文字列の(指定した開始位置から)左から検索し最初に検索文字が出現した位置を返す
LastIndexOf(検索文字,(開始位置)) :文字列の(指定した開始位置から)右から検索し最初に検索文字が出現した位置を返す
※開始位置未記入で最初からもしくは最後からとなる
※文字列は左から0からカウントで位置を示す半角でも全角でも1文字は1文字として示す
$STR="aあbcdefあg"
$A=$STR.IndexOf("あ")
$B=$STR.LastIndexOf("あ")
$C=$STR.IndexOf("c")
echo $A $B
1
7
3
[Convert]::ToString("1234", 8)
[Convert]::ToInt32("1234", 8)
[Convert]::Toint32("0xFF", 16) #整数として変換
[Convert]::ToString("0xFF", 10) #文字列として変換
$number.Tostring()
\ooo :8進数
\x :16進数
Windows環境では、S-JISのデータなどが多くあって、Powershellでは、ベースはutf-8となっています。
そのため、文字コードの切換は重要です。
古いWindowsPCでは、S-JIS(ANSI)で保存されているファイルが多いです。
そのためファイルの読込み時に-encoding パラメータが利用できるのであれば、それを利用して読み込むのが無難です。👉参照
Get-Contents "filename.csv" -encoding oem
932 shift_jis ANSI/OEM Japanese; Japanese (Shift-JIS)
20127 us-ascii US-ASCII (7-bit)
51932 euc-jp EUC Japanese
65001 utf-8 Unicode (UTF-8)
# S-JIS に変更
$OutputEncoding = [Console]::OutputEncoding
# US-ASCII に戻す
$OutputEncoding = New-Object System.Text.ASCIIEncoding
# utf-8に戻す
$OutputEncoding = New-Object System.Text.UTF8Encoding
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$PSDefaultParameterValues['*:Encoding'] = 'oem ' #windowsでは、shift-jis
$PSDefaultParameterValues['*:Encoding'] = 'ascii '
#追記のオプション
-Append
#文字コードを指定
-Encording oem # windows上では、S-JIS
-Encording utf-8 # utf-8 BOMなし
#文字コードを指定
-Encording oem # windows上では、S-JIS
-Encording utf-8 # utf-8 BOMなし
csvに残っている文字化けの残骸を削除するのに活用しています。
エスケープシーケンス文字で扱えない場合、16進数のASCIIコードを使用すれば扱えるようになります
-creplace を利用して制御文字を削除するプログラム
例:変数内の文字列に対して実施する
$after= $before -creplace "[\x00-\x0c\x10-\x1f\x22\x23]",""
例:ファイル内の文字に対して実施する
gc $FILENAME | % { $_ -creplace "[\x00-\x0c\x10-\x1f\x22\x23]","" } | Out-File -Encoding oem $TMP_FILE
※以下は正規表現上で使用する場合のスケープシーケンスです
ちなみに文字列表記上では、\rは、`r
例:$a="あいうえお`r"
バッチでの例:
IF '%VAR%'=='1' SET NUM=10
IF '%VAR%'=='1' (SET NUM=10)
PowerShellの例:
IF (条件) {実行内容}
IF (PowerShellステートメントの実行) {実行内容} #ステートメント実行でbool値などを返すものは利用できる
#パイプラインも利用できる
IF (変数への代入) {実行内容} #ステートメントなどの実行結果を変数に入れながらbool値分岐できる
IF () {} elseif () {} else {}
IF () {} else {}
例:
IF ($VAR -eq 1){
$NUM=10
}
Microsoftのドキュメントを参照 比較演算子について - PowerShell | Microsoft Learn
条件 比較演算子 など
-eq # 等しい(大文字、小文字を区別しない) 左= 右
-ceq # 等しい(大文字、小文字を区別する) 左= 右
-ne # 等しくない(大文字、小文字を区別しない) 左<>右
-cne # 等しくない(大文字、小文字を区別する) 左<>右
-gt #左は、右「より大きい」 左> 右
-ge #左は、右「以上」 左>=右
-lt #左は右「より小さい」 左< 右
-le #左は、右「以下」 左<=右
-like #ワイルドカード使用の比較一致 $VAR -like '*_20??.csv'
# ? は任意の 1 文字と一致
# * は任意の数の文字と一致
-clike #ワイルドカード使用の比較一致(大文字、小文字を区別する)
-notlike #ワイルドカード使用の比較不一致 $VAR -notlike '*_20??.csv'
-cnotlike #ワイルドカード使用の比較不一致(大文字、小文字を区別する)
-match #正規表現の比較一致 $VAR -match '\w\w\w_20\d\d.csv'
-cmatch #正規表現の比較一致(大文字、小文字を区別する)
-notmatch #正規表現の比較不一致
-cnotmatch #正規表現の比較不一致(大文字、小文字を区別する)
-is #型を調べ一致 $VAR -is [string]
#[bool][string][char][int][long][byte][float][double][decimal][object*]など
-isnot #型を調べ不一致
-contains #コレクションに値が含まれているか調べる 元要素群 -contans 調べる要素
調べる要素が、元要素群に含まれる場合 true
調べる要素が、要素群であれば、
調べる要素(群)が、元要素群と同じなら true
-ccontains #
-notcontains #コレクションに値が含まれていないことを調べる
-cnotcontains #
自動変数
$true $false #bool型のtrue、false をして予約されている
$null #null値の確認
bool値を論理演算する
-not #論理否定
! #論理否定
-and #論理積 ($test -eq 0) -and ($answer -ne 1)
-or #論理和
-xor #論理排他的論理和
型変換演算子
-as #型を変換する '2023' -as [int]
数値を二進数化して演算する
-bnot #ビット論理否定
-band #ビット論理積 10 -band 12 → 1010 1100 を and する 結果:1000 = 8
-bor #ビット論理和
-bxor #ビット論理排他的論理和
-shl #ビット左シフト シフトする数値 -shl シフト回数(何ビットシフトするか)
-shr #ビット右シフト
配列演算子
-join #左配列を右文字列を使って結合する @('2023','01','31') -join '/' 結果:2023/01/31
-split #左文字列から、右文字列(正規表現)で分割配列化 '2023/01/31' -split '\/+'
置換演算子
-replace #正規表現で置き換える(大文字、小文字を区別しない)
'西暦1234年' -replace '[0-9]{4}','****'
-creplace #正規表現で置き換える(大文字、小文字を区別する)
-f #書式演算:左のフォーマットに右の値を入れる '年={0}, 月={1}' -f (2023,12)
Unix コマンド
REM trを使用して制御文字を削除するプログラム
REM \000は、8進数表記
cat "sample.csv" | tr -d "\000-\014\016-\037\042\043" > "output.csv"
PowerShell スクリプトで書くと
# PowerShellでは、8進数表記ができないので16進表記で指定
# -creplaceを使用すると正規表現を利用できる
# -Encodeing oem は、SHIFT_JISで処理するための文字エンコードの設定
# gc : Get-Contentのエイリアス
# % : foreachのエイリアス
gc -encodeing oem "sample.csv" | % { $_ -creplace "[\x00-\x0c\x10-\x1f\x22\x23]","" } |Out-File -Encoding oem "output.csv"
Unixコマンド
sed -E "s/((IX|ID)[0-9]*)[^,]*,/\1,/g"
PowerShellスクリプト
% { $_ -creplace "((IX|ID)[0-9]*)[^,]*,","`$1," }
()でキャプチャグループを作成でき、sedでは、\1が、PoweShellでは、`$1となる
これを使うとキャプチャグループを抜き出すことができす
関数は、少々複雑です。
私は、Microsoft Leanの ドキュメントを参考に学習しました👉Microsoft Lean Powershell Function に関するページ
パイプラインからのデータの受取や、パイプラインでの受け渡しも可能です。
function 関数名 {
param(引き渡す変数)
begin{関数の最初だけ処理される}
process{パイプラインで入ってきたデータに対して繰り返し処理する内容を記述}
end{関数の最後だけ処理される}
}
$_は、自動変数$PSItemのエイリアスでどちらを使用しても同じ動きとなります。
※自動変数とはPowershell側で自動的に作られる変数
function 関数名 {
param(引き渡す変数)
begin{関数の最初だけ処理される}
process{
$Item=$_
}
end{関数の最後だけ処理される}
}
次の記述方法でもパイプラインからのデータを受け取ることができます。
Powershell上では、こちらの記述を推奨しているようです
function 関数名 {
param(
[Parameter(Mandatory,ValueFromPipeline)]$Item
)
begin{関数の最初だけ処理される}
process{
Write-Output $Item
}
end{関数の最後だけ処理される}
}
Microsoft Leanの ドキュメントを参考を参照ください👉Microsoft Learn 例外について知りたかったことのすべて
このブロックは、関数の中だけではなくメインの処理上でも使用しますが、ここの例では、関数内で記述してあります。
異常処理を記述するのに有効です。
function 関数名 {
param(引き渡す変数)
begin{関数の最初だけ処理される}
process{
try{ステートメントを記述}
catch{try内のステートメントで記述された内容でとらえられた異常の処理}
}
end{関数の最後だけ処理される}
}
Get-content gc
foreach %
Where-Object ?
& を使うと 変数がコード(ステートメント)として実行できる
$()を使うとかっこで囲まれたステートメントの実行後の結果を得ることができます。
これは、()内だけ先に実行し先に結果を得て次のステートメントにその結果を渡したい場合有効です。
また、文字列などで変数なのか文字なのかわかりにくい場合も有効に利用できます。
$data=1
$datapiece="piece"
Write-Output "Apple is $datapiece."
Write-Output "Apple is $($data)piece."
勉強中です。
for (変数初期値;条件;繰返し値)
例
for ($i=0; $i -le 10 ; $i++) {
Write-Output $i #パイプライン出力ができる
Write-Host $i #標準出力へ出力される
}