文字列を区切り文字に分割して不明な部分数を生成する方法と、結果を配列に収集する方法は?

文字列を区切り文字に分割して不明な部分数を生成する方法と、結果を配列に収集する方法は?

パスを含むいくつかの文字列を処理する必要があります。/これらの文字列を区切り文字に分割して未知のパス部分の数を生成する方法と、最終的に結果のパス部分を抽出する方法は?

cut明らかに部品の数を事前に知っておく必要があり、各部品を出力して使用したり、配列で収集することができないreadarrayためmapfile、選択するツールではありません。

答え1

bash単一文字の区切り記号の場合は、glob部分を無効にした後に分割+glob演算子を使用できます(リストコンテキストでは引用符なしで拡張を保持)。

string='foo/bar
baz/asd..'

IFS=/
set -o noglob
array=( $string )

でのみstring='/foo/'分割されることに注意してください(分割と同じ)。 、および に分割するには、次のようにします。"""foo"string='/foo'"""foo"""

IFS=/
set -o noglob
array=( $string'' )

それでもstring=''ゼロ要素の代わりに空の要素に分割されます。

zshsplit + globは/ emulationを除いて引用符なしの拡張を実行しません)、単一文字区切り文字に限定されないパラメータ拡張フラグを使用できます。shkshs

array=( ${(s[/])string} )

空の要素を削除するか、次の操作を行います。

array=( "${(@s[/])string}" )

空の要素は保持されます。/foo/次にそれをに分割し""、空の文字列をゼロ要素に分割します"foo"""

変数に格納されている区切り文字を使用して分割できます。

array=( "${(@ps[$delimiter])string}" )

このpフラグを使用すると、エスケープシーケンス(たとえば、、)を入力することもできます\0。これら2つのフラグには、改行から分割、NULから分割(たとえば、...の出力を分割するために使用できます)\nという短縮フラグがあります。f0find -print0grep -lZsort -zfiles=( ${(0)"$(grep -lZ pattern -- *)"} )

では、zsh次のこともできます。結ぶ指定された単一バイトを区切り文字として使用して、配列変数をスカラー変数に変換します。$pathinはzsh実際にこのように区切り文字で囲まれた特別な配列です$PATH:からインスピレーションを得ていますcsh)。どの変数でもこれを実行できます。たとえば、次のようになります。

typeset -T string array /

配列と/接続 - 分離。$string$array

答え2

Bashでは、read -ahere-stringを使用して文字列を配列に分割できます。

path=/foo/bar/doo
IFS=/ read -r -a parts <<< "$path"

fooこれにより、4つの要素(空)が含まれている配列がbar提供されますdoo

read改行文字はデフォルトで区切り文字として扱われるため、改行文字を含むパスには機能しません。これを防ぐために追加する必要があります-d ''が、問題があります。ここで、文字列は改行文字を追加してから最後の要素から削除する必要があります。

path=$'/path/with/new\nlines'
IFS=/ read -d '' -r -a parts <<< "$path"
parts[-1]=${parts[-1]%$'\n'}

parts[-1]配列の最後の要素を表し、一致する末尾の値を${var%text}削除するように拡張されます。)vartext

また、パスに繰り返されるスラッシュを含めることができる場合 (たとえば) foo//bar、途中に空の配列要素が表示されます。同様に、パスがスラッシュで終わると、最後に空の要素が表示されます。

これを無視したり、パスを前処理して削除したりできます。このような方法を使用して、重複したスラッシュを削除できます。

shopt -s extglob
path="${path//+('/')/'/'}"

末尾のスラッシュを削除します。

shopt -s extglob
path="${path%+('/')}"

//fooただし、ダブルスラッシュは単一(またはトリプルなど)スラッシュとは異なり、パス名の先頭にあります

答え3

readarray...各セクションを出力せずに次のものを使用できます。mapfile

mapfile/readarray を使用して文字列全体を指定し、区切り文字を設定します。例えば、

str='/f
oo/bar/'

mapfile -d / arr < <(printf '%s' "$str")

declare -p arr

出力:

declare -a arr=([0]="/" [1]=$'f\noo/' [2]="bar/")

関連情報