zsh を使用して、一致しない行を削除せずに消去します。

zsh を使用して、一致しない行を削除せずに消去します。

配列から一致しない行を削除するには、次のようにします。

array=( ${(M)array:#*${filter}*} )

しかし、配列も圧縮します。ただし、後で元の長さの他の配列とマージするので、配列を同じ長さに保つ必要があります。つまり、一致しない行を実際に削除せずに「空にしたい」ということです。配列の長さを変更したり、一致する行のインデックス番号を変更したくありません。

現在、一致しない文字列をプレースホルダとしてダミー文字列に置き換えてマージし、ダミー文字列を削除してこの問題を解決していますが、これは不器用な作業です。

答え1

引用符なしで展開すると、空の要素が削除されます。 Kornのようなシェルのように二重引用符とフラグを必要とする@か、それを使用して保存します。[@]

${var/pattern/replacement}また、Kornスタイルを代わりに使用する必要があります${array:#pattern}削除する要素、いいえ編集する彼らのコンテンツ。だから:

set -o extendedglob
array=( "${array[@]/#%^*$filter*}" )
print -rC1 -- "$array[@]"

ここでは、一致を先頭に固定し、最後に固定します(kshで結合できないことを除いて、Kornシェルと同じ)#。演算子でパターンを完全に一致させます。固定は暗黙的です。 、while全体の内容と一致する必要があり、開始と終了にのみ固定されます。/%${param:#pattern}pattern$param${param#pattern}${param%pattern}

^extendedglob否定演算子です。

zsh拡散演算子は、特に複数の演算子を結合し始めると非常に複雑になる可能性がありますが、他のほとんどの言語と同様に、常にこれを実行して配列要素を繰り返すことができます。

要素をその場で編集するのと同じです。

for (( i = 1; i <= $#array; i++ ))
  if [[ $array[i] != *$filter* ]] array[i]=

または、新しい配列を作成します。

new_array=()
for element ( "$array[@]" )
  case $element in
    (*$filter*) new_array+=( "$element" );;
    (*)         new_array+=( '' )
  esac

または:

new_array=()
for element ( "$array[@]" ) {
  [[ $element = *$filter* ]] || element=
  new_array+=( "$element" )
}

答え2

array=( "${(@M)array##*${filter}*}" )

これは配列内のすべての要素を保持し、各要素で最長の接頭辞を削除しますが、一致する部分だけを保持するように##patternフラグを使用します。空の要素が結果から削除されないように、M二重引用符とフラグが必要です。@

関連情報