0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PowerShellの初めの一歩

目的

PowerShellを使用した簡単なスクリプトを作成して理解を深める。
一通りPowerShellの基本的な動作を確認できるスクリプトを作成する。

環境

Windows11
PSVersion 7.4.2

どんな処理ができるスクリプトを作成するか

次の処理ができるスクリプトを作成する。

  1. コンソールで日本語の文字列を1行ずつ入力できる
  2. 改行コードが含まれていた場合スクリプトを強制終了させる
  3. 一行ずつ入力して'exit'と入力されたとき入力モードを終了する
  4. 終了後スクリプトが配置された階層にフォルダを生成する
  5. 生成したフォルダに入力値が記録されたテキストファイルを出力する

コンソールから文字列を受け取る

sample1.ps1
$demoText = Read-Host "Please enter a string"
Write-Host $demoText

処理内容

  1. コンソールに入力された文字列を受け取る
  2. コンソールに受け取った文字列を出力している

補足

予約語などで例外となる場合もあるが基本的に$がついているものは変数として扱う。
動詞-名詞で構成されたPowershell特有のコマンドをコマンドレットと呼んでいる。従来のコマンド プロンプトでは複雑となるような処理を短いコマンドで実装することが可能となる。

  • Read-Host
    コンソールからの入力読み込み時に使用
  • Write-Host
    コンソール出力時に使用

テキストファイルを出力する

sample2.ps1
$demoText = Read-Host "Please enter a string"
$demoText | Out-File -FilePath .\Results.txt

処理内容

  1. コンソールに入力された文字列を受け取る
  2. スクリプトと同階層にResults.txtファイルを生成する。ファイルの内容は1で入力された文字列である

補足

  • Out-File ファイル出力時に使用
  • -FilePath
    コマンドレットの後に-をつけてコマンドレットごとに登録されたパラメータを指定する。コマンドレットの処理を操作することができる。今回では-FilePathを使用してファイルの出力先を指定している。
    どういったパラメータを指定できるかは公式ドキュメント等でも確認できる。
    参考:https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.utility/out-file?view=powershell-5.1

PowerShellにおける配列

sample3.ps1
$demoTexts = @()
$demoTexts += "hoge"
$demoTexts += "fuga"
$demoTexts += "piyo"
Write-Host $demoTexts 

処理内容

  1. 空の配列を生成する
  2. 配列に格納する要素を追加する。(実際には要素を追加した新規の配列を生成している。)
  3. 配列をコンソールに出力する

補足

@()と宣言することで空の配列を生成できる。
基本的に配列は要素数が固定である場合に使用する。そのためサンプルのソースのように配列を扱うと処理速度は遅い。項目数の増減があるような処理はコレクションを利用したほうが処理速度は速くなるためコレクションを利用する方が実用的である。
今回配列を利用しているのはコレクションについての説明を避け、なるべく簡潔に実装とその実装の説明を済ませたいため。

whileを使用したループ処理

sample4.ps1
$continue = $true
$demoTexts = @()

while ($continue) {
    $inputText = Read-Host "Please enter texts (or 'exit' to finish)"
    if ($inputText -ceq "exit") {
        $continue = $false
    }
    else {
        $demoTexts += $inputText
    }
}
Write-Host $demoTexts

処理内容

  1. \$continue,\$demoTextsと名前を付けた変数を宣言する。\$continueはブール値である
  2. \$continueが\$trueの間3~5のWhile内の処理を繰り返し実行する。\$falseの場合while内の処理から抜け、6の処理を実行する
  3. \$inputTextに入力値を格納する
  4. \$inputTextの文字列がexitの場合、$continueにブール値falseを設定する。exit以外の場合5の処理を実行する
  5. \$demoTextsに\$inputTextを追加する
  6. \$demoTextsをコンソールに出力する

補足

  • ブール値の扱い
    PowerShellでブール値を扱う場合\$true,\$falseと表記する。
  • 文字列比較
    -ceqは大文字小文字を区別したうえで文字列の比較を行い、一致する場合trueを返す。-eqを使用している場合は大文字、小文字を区別せずに比較を行う。

-ceqのc
大文字、小文字を区別する事をcase-sensitiveというため

foreachを使用したループ処理

sample5.ps1
$demoTexts = @("hoge", "fuga" , "piyo")

foreach ($item in $demoTexts) {
    Write-Host $item
}
実行結果
hoge
fuga
piyo

処理内容

  1. 配列を宣言する
  2. 配列の要素を一つずつ取り出し、コンソールに出力する

補足

  • forループを使用した場合
    配列を単純に一つずつ取り出して処理を繰り返すだけなら可読性はいまいちだと思うが以下のように書ける。
sample6.ps1
$demoTexts = @("hoge", "fuga" , "piyo")

for ($index = 0; $index -lt $demotexts.Count; $index++) {
    "{0}" -f $demoTexts[$index]
}

-lt,-fについて
-ltは less than を表していて配列の要素数を超えないよう制限している。
-f はフォーマット演算子と呼ばれ-fの左側で指定した書式を右側の要素に設定することができる。

スクリプトの強制終了

sample7.ps1
$continue = $true
$demoTexts = @()

while ($continue) {
    $inputText = Read-Host "Please enter texts (or 'exit' to finish)"
    if ($inputText -match "`n") { 
        throw "The script has finished executing because it encountered input newline characters."
    }
    if ($inputText -ceq "exit") {
        $continue = $false
    }
    else {
        $demoTexts += $inputText
    }
}
Write-Host $demoTexts

処理内容

  1. \$continue,\$demoTextsと名前を付けた変数を宣言する。\$continueはブール値である
  2. \$continueが\$trueの間3~6のWhile内の処理を繰り返し実行する。\$falseの場合while内の処理から抜け、7の処理を実行する
  3. \$inputTextに入力値を格納する
  4. \$inputTextの入力中に改行コードが入力された場合スクリプトを終了する
  5. \$inputTextの文字列がexitの場合、$continueにブール値falseを設定する。exit以外の場合6の処理を実行する
  6. \$demoTextsに\$inputTextを追加する
  7. \$demoTextsをコンソールに出力する

補足

おそらく一番簡単な処理の中断方法。throw の後に文字列を書くことで任意の文字列を表示させてスクリプトを強制終了することができる。
実際に処理が中断した場合コンソールには次のように表示される。

Line |
   7 |          throw "The script has finished executing because it encounter …
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The script has finished executing because it encountered input newline characters.

完成スクリプト

sample8.ps1
$continue = $true
$results = @()
$outputText = ""
$inputCount = 0

while ($continue) {
    $inputText = Read-Host "Please enter texts (or 'exit' to finish)"
    if ($inputText -match "`n") { 
        throw "The script has finished executing because it encountered input newline characters."
    }
    if ($inputText -eq "exit") {
        $continue = $false
    }
    else {
        $results += $inputText
    }
}
if ($results.Count -eq 0) {
    $outputText = "no input"
}
else {
    foreach ($val in $results) {
        $outputText += $val
        $inputCount += 1
        if ($inputCount -ne $results.Count) {
            $outputText += "`n"
        } 
    }
}
$outputText | Out-File -FilePath .\Results.txt -NoNewline

処理内容

  1. 変数を宣言する
  2. \$continueが\$trueの間3~6のWhile内の処理を繰り返し実行する。\$falseの場合while内の処理から抜け、7の処理を実行する
  3. \$inputTextに入力値を格納する
  4. \$inputTextの入力中に改行コードが入力された場合スクリプトを終了する
  5. \$inputTextの文字列がexitの場合、$continueにブール値falseを設定する。exit以外の場合6の処理を実行する
  6. \$resultsに\$inputTextを追加する
  7. \$resultsの要素数が0の場合、コンソールにno inputと出力する。\$resultsの要素数が0でない場合、8~9のforeach内の処理を要素数分繰り返し実行する
  8. \$resultsの要素を\$outputTextに連結し、\$countをインクリメントする
  9. \$countと\$resultsの要素数が一致しない場合、\$outputTextの文字列に改行コードを連結する
  10. スクリプトと同階層にResults.txtファイルを生成する。ファイルの内容は$outputTextである

補足

最初の1の変数宣言時に$outputText = ""と明示的に文字列と宣言しているが$outputTextと型を書かずに宣言してもPowerShell側で文字列として処理される。

10のファイル出力時デフォルトで最後に空行が挿入される。-NoNewlineのパラメータを付与すると最後に空行を挿入せずにファイルを出力することができる。

Out-Fileの-Encodingパラメータ
実用的にスクリプトでファイルを置換等する場合、よく使用するパラメータになるかと思う。このパラメータを使用することで文字コードやBOMの有無を指定できる

まとめ

かなり基本的な内容で頻繁にスクリプトを書くわけではないのでよく忘れてしまう。私がスクリプトを作成する場合一から作るということはあまりなく、ChatGPTに投げて帰ってきたスクリプトのコードを手直しして使用することが多い。そういったときにざっとよく使う処理を確認できる内容になればと思い記事にまとめた。

実務ではExcelのブック内の情報を参照して参照結果を別のブックに出力したり、Thymeleafの一部のタグを置換したりなどでPowerShellを使用した。気が向いたらそのあたりも書けたら…

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?