Bashで配列をソートする方法 質問する

Bashで配列をソートする方法 質問する

たとえば、Bash に配列があります。

array=(a c b f 3 5)

配列をソートする必要があります。コンテンツをソートして表示するだけでなく、ソートされた要素を含む新しい配列を取得します。ソートされた新しい配列は、完全に新しい配列でも古い配列でもかまいません。

ベストアンサー1

実際にはそれほど多くのコードは必要ありません。

IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS

要素内の空白をサポートします(改行でない限り)。そしてBash 3.x で動作します。

例えば:

$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]

注記:@sorontarは指摘した*要素にまたはなどのワイルドカードが含まれている場合は注意が必要です?

sorted=($(...)) の部分では、「split and glob」演算子が使用されています。glob をオフにする必要があります。set -fまたは、set -o noglobまたはshopt -op noglob、またはのような配列の要素は、*ファイルのリストに展開されます。

何が起こっていますか:

その結果、次の 6 つのことが次の順序で発生します。

  1. IFS=$'\n'
  2. "${array[*]}"
  3. <<<
  4. sort
  5. sorted=($(...))
  6. unset IFS

まず、IFS=$'\n'

これは、次のように 2 と 5 の結果に影響を与える、操作の重要な部分です。

与えられた条件:

  • "${array[*]}"最初の文字で区切られたすべての要素に展開されますIFS
  • sorted=()の各文字ごとに分割して要素を作成しますIFS

IFS=$'\n' 物事を設定する要素は次のように展開されます新しい行区切り文字として使用し、その後、各行が要素になるように作成します。(つまり、新しい行で分割します。)

改行で区切ることは、それがsort動作(行ごとにソート)であるため重要です。のみ新しい行はそれほど重要ではありませんが、スペースやタブを含む要素を保持するには必要です。

のデフォルト値IFSスペースタブ、 に続く新しい行、そして私たちの業務には不適切でしょう。

次にsort <<<"${array[*]}"

<<<と呼ばれるここに文字列は、上で説明したように の展開を受け取り"${array[*]}"、それを の標準入力に入力しますsort

この例では、sort次の文字列が入力されます。

a c
b
f
3 5

以来sort ソート、それは生成します:

3 5
a c
b
f

次にsorted=($(...))

$(...)と呼ばれる部分コマンド置換は、その内容(sort <<<"${array[*]})を通常のコマンドとして実行し、その結果として標準出力文字通り、どこにでも行けます$(...)

この例では、単純に次のように記述した場合と似たものが生成されます。

sorted=(3 5
a c
b
f
)

sorted次に、このリテラルを新しい行ごとに分割して作成された配列になります。

最後に、unset IFS

これにより、 の値がIFSデフォルト値にリセットされます。これは良い方法です。

これは、スクリプトの後半で依存するものに問題が発生しないようにするためですIFS。(そうしないと、物事を入れ替えたことを覚えておく必要があり、複雑なスクリプトでは非現実的になる可能性があります。)

おすすめ記事