1. 概要

Bash は、ほぼすべてのLinuxシステムにインストールされている多用途のシェルです。

インタラクティブシェルとしての価値に加えて、bashを使用してあらゆる種類のタスクを自動化することもできます。 これらのタスクは、多くの場合、データのリスト(たとえば、ファイルのリスト、またはIPアドレスのリスト)を処理します。

これらのリストを配列に整理できます。 Bashは、インデックス付き配列(アイテムを番号で参照する場合)と連想配列(アイテムを名前で参照する場合)の両方を使用します。 連想配列は、他のプログラミング言語ではマップまたは辞書と呼ばれることがよくあります。

チュートリアルでは、いくつかのリストを配列に割り当てます。 次に、配列から重複をふるいにかける方法を見ていきます。これにより、一意のエントリのみが含まれ、重複は含まれなくなります。

2. 配列の宣言と使用

Bashアレイについては、このサイトの他の場所で詳しく説明されています。

簡単に言うと、両方の種類の配列(インデックス付きと連想)を宣言する方法を知る必要があります。 また、配列全体を参照する方法も知っておく必要があります。

括弧を使用して、インデックス付き配列を定義できます。

ip_addrs=(192.168.2.101 192.168.2.105 192.168.2.201 192.168.2.110)

個々のインデックスではなく配列全体を操作するために、数値の代わりに@記号を使用します。

これにより、インデックスを追跡せずに、配列内のすべての要素をループできます。 たとえば、各アドレスに1回pingを実行するとします。

for ip in ${ip_addrs[@]}; do
    ping -D -c1 $ip
done

2.1. 連想配列

一部のデータでは、番号付きリスト以上のものが必要です。 連想配列を使用すると、データ(「値」)に名前(「キー」)を付けることができます。 NoSQLデータベースも、この方法でデータを整理することがよくあります。

次のように、一度に複数のキーと値のペアを割り当てることができます。

declare -A ips_by_hostname=([mysql]=192.168.2.101 [nginx]=192.168.2.99 [smtp]=192.168.2.105)

最初に、declare-A。を使用して変数を連想配列として「宣言」することを忘れないでください。

すべての値またはすべてのキーの配列を生成することもできます

すべての連想配列の値を一覧表示するには、インデックス付き配列と同様の構文を使用します。

$ echo "${ips_by_hostname[@]}"
192.168.2.101 192.168.2.105 192.168.2.99

キーを表示するには、配列変数名の前に感嘆符を追加します。

for host in "${!ips_by_hostname[@]}"; do
    echo "key: $host value: ${ips_by_hostname[$host]}"
done
key: mysql value: 192.168.2.101
key: smtp value: 192.168.2.99
key: nginx value: 192.168.2.105

3. 一意の値のみ

では、元の質問に戻りましょう。配列に重複が含まれている場合、それらを削除する簡単な方法は何ですか?

3.1. 連想配列キーに割り当てる

連想配列のキーは常にその配列に固有である必要があります。 1つのキー、1つの値。

これを有利に使用できます。 配列をループして各項目を連想配列のキーに割り当てると、その配列のキーは元の配列の一意の値のセットになります。

declare -a ip_addrs=(192.168.1.101 192.168.1.105 192.168.1.105 192.168.1.106)

declare -A uniq_tmp

for ip in "${ip_addrs[@]}"; do
    uniq_tmp[$ip]=0 # assigning a placeholder
done

echo "unique: ${!uniq_tmp[@]}" # only the keys

これにより、重複する192.168.1.105を省略して、3つのIPアドレスが出力されます。 このソリューションには、他のプログラムを実行せずに、すべてbash内で機能するという利点があります。

3.2. sort-uを使用する

シェルスクリプトを作成する場合、他のオプションがあります。 GNUソートユーティリティを介して配列を渡すことができます。

これによりアイテムの順序が変更されるため、特定のスクリプトで重要になる場合は、この点に注意してください。

sort コマンドは入力を1行ずつ並べ替えるため、配列を複数の行に分割する必要があります。

sortコマンドの-uオプションは、重複する行を破棄します。

したがって、次のようにIPアドレスの配列を操作できます。

uniqs_arr=($(for ip in "${ip_addrs[@]}"; do echo "${ip}"; done | sort -u))

これで、一意の並べ替えられた値の配列ができました。

3.3. trおよびawkを使用する

Unixツールの残りのコレクションを使い始めると、どこでも解決策を見つけ始めます。 bashを超える強力なツールの1つは、awkです。

uniqs_arr=($(tr ' ' '\n' <<<"${ip_addrs[@]}" | awk '!u[$0]++' | tr '\n' ' '))

これはより複雑な領域に入ります。 しかし、それを分解するには:

  1. 配列を再び別々の行に分割する必要があります。 今回は、 tr を使用して、アイテム間のスペースを改行(\ n)に変換します。
  2. これをawkにパイプし、一意の行のみを引用するようにします。
  3. 次に、もう一度 tr を使用して、出力を再び配列に変換します。

この方法の利点は、配列の要素の順序を保持できることです。

4. 結論

Bash配列には、インデックス付きと連想の2つのタイプがあります。 両方を一緒に使用すると、いくつかの便利なデータ構造操作へのショートカットが可能になります。

このチュートリアルでは、両方の種類のbash配列を作成して操作しました。 配列をフィルタリングして、一意の値のみが含まれるようにする3つの方法を検討しました。

これらの手法を使用すると、より複雑で便利なプログラミング手順をすべてbashで実行できます。