Powershell入門 - 07. ループステートメント

今回は繰返し処理について学んでいきます。  
Powershellの繰返し処理は大きく3つあります。

1. for文による繰返し
2. foreach文による繰返し
3. ForEach-Objectによる繰返し
4. while文による繰返し

このうち3については別で紹介するとして、今回は1,2について扱っていきます。
※4については、この入門では扱いませんので、興味のある人は自分で調べてみてください。

# 1. for文による繰返し
まずは基本の**for文**から説明します。
```powershell
for(初期化式;継続条件式;ステップ式){
    # 実行したい処理
}
```
これらの書き方もやはりCやJavaによく似ています。  
ただし、if文と同じく比較演算子がPowershellでは少し独特なため、実際の見た目は少し異なります。
では、実際の実装例を見てみましょう。
```powershell
for($i=0; $i -lt 10; $i++){
    Write-Host $i
}
```
上記は0～9までの値を順番に表示するスクリプトです。
やはり、継続条件式に書かれた`-lt`が他の言語で慣れた人からすると分かりにくく感じますね。  
何度も書いて、慣れるようにしましょう。

---
#### 例題1.
for文を使って、1～10までの合計値を表示しなさい。

#### 例題2.
以下の配列の中身を1行ずつすべて表示しなさい。

```powershell
$arr = "abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"
```
---

## 1.1. break文とcontinue文
ループステートメントでは、継続している間は基本的には毎回`{}`で書かれた内容を実施します。
もしこの処理の流れを変えたい場合は、**break文**や**continue文**を使用します。

### 1.1.1. break文
こちらはループを強制的に抜ける場合に利用します。
例えば、配列の中から特定の値を探す処理を見てみましょう。

```powershell
$arr = "a","b","c","d","e","f","g","h","i","j","k","l","m","n"
$s = Read-Host "英小文字1文字を入力"

for($i=0; $i -lt $arr.Length; $i++){
    if($arr[$i] -eq $s){
        Write-Host ("Found!! pos=" + $i)
        break
    }
}
```
まず外側のfor文は配列の中身を順番に確認するためのものになります。
この中で配列arrのi番目の要素がsと一致するかを調べています。
一致しなければ次のループへ進みますが、一致した場合はその位置を表示します。
そして、見つかったらそれ以降を調べる必要がないため、breakで処理を抜けます。

このようにbreakを使うのは、「これ以上繰返し処理を続ける必要がないとき」になります。

### 1.1.2. continue文
こちらは特定のループをスキップする場合に使います。
以下の例を見てみましょう。
```powershell
$sum = 0
for($i=1; $i -le 10; $i++){
    if($i % 2 -eq 1){
        continue
    }
    $sum += $i
}
Write-Host $sum
```

まず、if文を無視して読み進めると、1～10までの合計値を求める処理を行っていることが分かります。
ここで、ifの条件をみると、「変数iが奇数」という条件が書かれています。
continue文は実行した瞬間に次のループへ移るため、この場合は「変数iが奇数の場合はスキップ」という処理となります。

このようにcontinue文を使うのは、「繰返し処理したくない特定のステップを飛ばすため」になります。
上記の例から分かるように、break文もcontinue文も基本的にはif文とともに使われることが多いです。

---
#### 例題3.
for文を使って、1～100までの合計値を計算しなさい。
ただし、合計値が1000を超えた時点でfor文を中断し、その時点での合計値を出力しなさい。

#### 例題4.
以下の配列の中身を1行ずつすべて表示しなさい。
ただし、"m"が含まれている文字列については表示しないこと

※文字列が特定の文字列を含むかどうかの判定は、`$文字列.Contains(検索対象)`で判定できる。

```powershell
$arr = "abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"
```
---

# 2. foreach文による繰返し
foreach文は配列などのデータの集まり（コレクションといいます）に特化した繰返し処理になります。
```powershell
foreach($変数 in コレクション){
    # 実行したい処理
}
```
foreach文では、コレクションから値を1つずつ取ってきて、変数に格納します。
変数はそのループ内で使用可能なので、この変数を使って{}内の処理を記述します。

具体例として、例題2をforeachで書いてみます。
```powershell
$arr = "abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"
foreach($v in $arr){
    Write-Host $v
}
```
配列による繰返し処理の場合、
- for文ではループ変数は配列の添え字
- foreach文ではループ変数は配列の中身
という違いがあるので注意しましょう。

---
#### 例題5.
例題4をforeach文で解きなさい

#### 例題6.
例題1をforeach文で解きなさい

---

# 3. コマンドレットとループステートメントの連携
[04.変数](./69a20b5280277f42027d#22-要素へのアクセス方法)でも説明した通り、コマンドレットの結果はオブジェクトとして返却され、モノによっては配列のように扱うことが出来ました。

では、コマンドレットの結果をforeach文と組み合わせて使ってみます。

```powershell
$gci = Get-ChildItem
foreach($v in $gci){
    Write-Host ($v.PSPath + ", " + $v.Name)
}
```

結果は以下の通りとなりました。
```
(base) PS D:\powershell\data> 
$gci = Get-ChildItem
foreach($v in $gci){
    Write-Host ($v.PSPath + ", " + $v.Name)
}
Microsoft.PowerShell.Core\FileSystem::D:\powershell\data\sampleFolder1, sampleFolder1
Microsoft.PowerShell.Core\FileSystem::D:\powershell\data\sampleFolder2, sampleFolder2
Microsoft.PowerShell.Core\FileSystem::D:\powershell\data\sample1.py, sample1.py
Microsoft.PowerShell.Core\FileSystem::D:\powershell\data\sample1.txt, sample1.txt
```

このようにGet-ChildItemなど、結果が複数個返ってくるような処理の場合、実行結果をforeach文に渡してあげることで、1件ずつ処理することが出来ます。
コマンドレット、if文、for文(foreach文)を組み合わせることで、大抵の処理は書くことが出来るようになります。
是非、覚えていきましょう。

---

#### 例題7.
以下の変数に含まれるすべての中身のLastWriteTimeを表示しなさい。
```
$gci_r = Get-ChildItem -Recurse
```

#### 例題8.
例題7の変数に含まれるすべてのファイルサイズの合計値を求めなさい。
各ファイルのファイルサイズはLength属性で確認できる。

---

Prev : [06. 条件ステートメント](./906f5bdc719b34052b46)
Next : [08. 文字列、パス文字列の操作](./334a6b2d37c0edf11be6)

[目次へ戻る](./926b8053a031539437a3)