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
두 번째 그룹, 즉 위의 첫 번째 문자가 발견된 문자를 찾습니다 .d
xyzd
하위 문자열의 위치를 찾으려면 표준 셸에서 다음을 수행할 수 있습니다.
haystack=abcdefghijklmnopqrstuvwxyz
needle=jkl
x=${haystack%%$needle*};
이제 x
해당 하위 문자열 앞의 문자열 부분이 포함됩니다 "${#x}"
(이 경우 0부터 시작하는 위치).jkl
9
문자 집합에서 문자(바이트)의 위치를 찾으려면 다음과 같이 유사하게 사용할 수 있습니다.
haystack=abcdefghijklmnopqrstuvwxyz
needle=xqe;
x=${haystack%%[$needle]*};
여기는 "${#x}"
4입니다. 두 방법의 단점은 검색 중인 문자열/문자를 찾을 수 없으면 x
전체가 포함되므로 일치하는 항목이 있는지 확인하려면 전체 길이(0이 아님)와 비교 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
. 그러나 이것이 동일한 방식으로 작동하는 두 가지 이유가 있습니다 expr index
.
귀하가 제공한 예에서 귀하는 다음을 검색하고 있습니다.XYZD, 이는 문자열에 존재하지 않지만 문자열은 다음으로 끝나기 때문에XYZ, expr
"d"를 정상적으로 제거하고 일치 항목을 반환합니다. 이 점에서 Zsh의 행동이 더 합리적이라고 주장할 수도 있지만, 물론 이것이 중요한 문제라면 저는 Zsh를 고수하겠습니다.
Zsh가 다른 또 다른 이유는 ${(SB)v#...}
문자열이 존재하지 않으면 1을 반환한다는 것입니다.아니요성냥. 예를 들어,
echo ${(SB)v#a}
echo ${(SB)v#7}
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]}