Zshはbashと同じですか?
expr index "abcdefghijklmnopqrstuvwxyz" xyzd
部分文字列のインデックスを見つけようとしています。
答え1
zsh
非標準のexpr
使用法(btwには関係ありません)の組み込みの代替案を探している場合は、bash
次のことができます。
$ a=abcdefghijklmnopqrstuvwxyz b=xyzd
$ echo ${a[(i)[$b]]}
4
を使用するとi
インデックスを取得できます最初一致します(一致するものがない場合は、干し草の山の長さを追加します)。代わりにI
、最後の一致を取得します(または一致がない場合は0)。
POSIXに似たシェルを使用(bash
および含むzsh
)
$ s=${a%%[$b]*}
$ echo "$(($#s + 1))"
4
答え2
GNU coreutilsパッケージの実装は、expr
どのシェルを使用しても同じ方法で使用できる外部ユーティリティです。
存在するzsh
、
expr index "abcdefghijklmnopqrstuvwxyz" xyzd
4
シェルbash
や他のシェルと同様に返されます。
index
GNUの仕事はexpr
次のとおりです。基準expr
これはexpr: syntax error
、特定の実装がないシステムでバグが発生する可能性があることを意味しますexpr
。どのシェルを使用するかは問題ではありません。
答え3
expr index "abcdefghijklmnopqrstuvwxyz" xyzd
部分文字列のインデックスを見つけようとしています。
部分文字列インデックスまたは文字インデックス?部分文字列(文字列には存在しません)ではなく、expr index
2番目のグループ、つまり上記の最初の文字が見つかった文字を探します。d
xyzd
部分文字列の位置を見つけるには、標準シェルで次のようにします。
haystack=abcdefghijklmnopqrstuvwxyz
needle=jkl
x=${haystack%%$needle*};
これでx
、その部分文字列の前の文字列部分が含まれます"${#x}"
(この場合は0から始まる位置)。jkl
9
文字セット内の文字(バイト)の位置を見つけるには、次のように使用できます。
haystack=abcdefghijklmnopqrstuvwxyz
needle=xqe;
x=${haystack%%[$needle]*};
ここは"${#x}"
4です。 2つの方法の欠点は、検索中の文字列/文字が見つからない場合はx
全体を含むため、一致するものがあるかどうかを確認するには、全長(ゼロではない)と比較するhaystack
必要があります。"${#x}"
haystack
haystack=abcdefghijklmnopqrstuvwxyz
needle=qqq
x=${haystack%%$needle*}
if [ "${#x}" = "${#haystack}" ]; then echo "$needle not found"; fi
答え4
Kusalanandaがすでに彼のコメントで指摘したように、expr
zshでも使用できますが、Zsh組み込みこれを行う方法。
答えは「いいえ」ですが、以下の内容が含まれています。
v="abcdefghijklmnopqrstuvwxyz"
i=${(SB)v#cdef}
これは3に設定されますi
。しかし、これが同じように機能する理由は2つありますexpr index
。
あなたが提供した例では、あなたは以下を検索しています。XYZD、これは文字列には存在しませんが、文字列は次に終了するためXYZ、expr
「d」を正常に削除し、一致を返します。この点でZshの行動はより合理的であると主張するかもしれませんが、もちろんこれが重要な問題であれば、私はZshに固執します。
Zshが別の別の理由は、${(SB)v#...}
文字列が存在しない場合は1を返すことです。いいえマッチ。例えば、
echo ${(SB)v#a}
echo ${(SB)v#7}
1を返します。これだけでは、不一致と最初の文字の一致を区別することはできません。考えられる解決策の1つは、レースの位置と長さを計算することです。
# N returns the length of the match
index_and_length=${(SBN)v#...}
# index_and_length contains the index, a space, and the length
if [[ ${index_and_length#* } == 0 ]]
then
echo no match
else
index=${index_and_length% *}
echo match at index $index
fi
UDPATE:この投稿のコメントでわかるように、私が間違って理解したexpr index
ため、答えは不適切です。ただし、検索する「文字列」がグローバルパターンであるため、これを調整できます。したがって、角かっこが操作を実行します。
# Search for the first occurance of one of the letters x y z d
index_and_length=${(SBN)v#[xyzd]}