Bash의 `expr index "abcdefghijklmnopqrstuvwxyz" xyzd`에 해당하는 Zsh

Bash의 `expr index "abcdefghijklmnopqrstuvwxyz" xyzd`에 해당하는 Zsh

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

4bash이나 다른 쉘 에서와 마찬가지로 반환됩니다 .

indexGNU의 작업은 expr다음과 같습니다.기준expr이는 expr: syntax error특정 구현이 없는 시스템에서 버그가 발생할 수 있음을 의미합니다 expr. 어떤 쉘을 사용하는지는 중요하지 않습니다.

답변3

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

하위 문자열의 인덱스를 찾으려고 합니다.

하위 문자열 인덱스 또는 문자 인덱스? 하위 문자열 (문자열에 존재하지 않음) 이 아닌 expr index두 번째 그룹, 즉 위의 첫 번째 문자가 발견된 문자를 찾습니다 .dxyzd

하위 문자열의 위치를 ​​찾으려면 표준 셸에서 다음을 수행할 수 있습니다.

haystack=abcdefghijklmnopqrstuvwxyz
needle=jkl
x=${haystack%%$needle*};

이제 x해당 하위 문자열 앞의 문자열 부분이 포함됩니다 "${#x}"(이 경우 0부터 시작하는 위치).jkl9

문자 집합에서 문자(바이트)의 위치를 ​​찾으려면 다음과 같이 유사하게 사용할 수 있습니다.

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가 이미 그의 의견에서 지적했듯이 exprzsh에서도 사용할 수 있지만 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]}

관련 정보