シェルスクリプトで引数でループする処理を書くときは “${@}” は不要だった

2022-01-28Bash

はじめに

個人的にはシェルスクリプトでループ処理を書くと速度が出ず、また記載が冗長となるためあまり使いません。

それでも分岐処理を含めて繰り返し処理したい場合にはループを書くことがあります。

シェルスクリプト実行時に渡される「コマンドライン引数」でループを回すこともありますが、先日今まで書いていた処理がもっとかんたんに書けることを知りました。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ head -n 2 /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

今まで記述してた「コマンドライン引数」を使ったループ処理

今までコマンドライン引数を使ったループ処理を記述したい場合には、 for"${@}" 変数を使って記述していました。

以下がそのコードになります。

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o noclobber

for I in "${@}"; do
  echo "$I"
done

test1.sh という名前で保存し、実行してみます。

# 実行権限を与えてあげましょう
$ chmod 700 test1.sh

# 実行
$ ./test1.sh a b "c d" " e "
a
b
c d
 e

第 3 引数、第 4 引数にはスペースを含んでいるため、ダブルクォート(")で囲んでやる必要があります。
また、参照する際にも "${@}" という形式で for 構文に渡してやる必要があります。

上記 2 点が大事なポイントですし、「知らないとハマるよね(ドヤァ」と思っていました。

つい先日までは。

「コマンドライン引数」を使ったループ処理に "${@}" の記載は不要

先日、別の方が作成されているシェルスクリプトを拝見することがありました。

そこで書かれているループ処理の一部を抜粋すると、以下のようになっていました。

for I; do
  ...
done

「あれ?、 in 以降が記載されていない?」

スクリプトでやろうとしていることを見ると、コマンドライン引数を受け取りループを回すというものでした。

「もしかして、 "${@}" いらない?」

"${@}" は書かなくても良かったみたいです。
先程のループ処理のコードは以下と同義になります。

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o noclobber

for I; do
  echo "$I"
done

test2.sh という名前で保存し、実行してみます。

# 実行権限を与えてあげましょう
$ chmod 700 test2.sh

# 実行
$ ./test2.sh a b "c d" " e "
a
b
c d
 e

全く同じ結果が出力されていますね。

ポイントはミスりそうな記述 "${@}" を書かなくてもいいし、覚える必要もないという点です。

ひとこと

人から学べることはたくさんありますね。

シェルの勉強会、いつも参加したいなぁと思っているんですが、子供が 5 人もいると土日はいつも大変な妻の代わりにこどもの面倒をみる必要があり、参加は難しい。

平日の定時以降にやってくれると嬉しいなぁ。

2022-01-28Bash