나는 주사위를 굴리기 위해 작은 순수 bash 스크립트를 만들고 있으므로 배열을 조작해야 합니다. 나는 다른 언어에서 수행되는 것과 유사한 작업을 수행하고 싶습니다 filter
. 즉, 배열에서 일부 내용을 추출하여 다른 배열에 넣는 것입니다.
다른 작업(예: 인덱스 간 슬라이싱)에 배열을 사용하는 것이 훨씬 쉽기 때문에 값을 bash 배열로 유지하고 싶습니다.
루프를 사용하여 이 작업을 수행 할 수 있지만 for... do... done
패턴 일치가 예상대로 작동하지 않는 이유가 궁금합니다.
shopt -s extglob;
dicerolls=(a b lol kek yolo swag );
c=(${dicerolls[@]/!(kek)/});
declare -p c;
# Expected: declare -a c=([0]="kek")
# Got: declare -a c=([0]="k")
# One can also see it with this example:
dicerolls=(20 15 7 8 9 0 14 5 6 200 144); c=(${dicerolls[@]/!(14)/}); declare -p c;
# Expected: declare -a c=([0]="14")
# Got: declare -a c=([0]="4")
# Oddly, this works for single-character values
dicerolls=(20 15 7 8 9 0 14 5 6 200 144); c=(${dicerolls[@]/!(8)/}); declare -p c;
# Got: declare -a c=([0]="8")
@ikkachu의 더 간단한 예 편집
var="abcd"
echo "${var/!(abcd)/}"
# Result: d
# Expected: abcd
${dicerolls[@]/%!(14)/}
패턴에 없는 항목을 올바르게 일치(및 삭제)하는 것처럼 보이지만 패턴에 포함된 항목을 만나면 일치 항목의 마지막(또는 사용된 경우 첫 번째) 문자 만 가져오는 것 같습니다 . 설명서에서 일종의 길이 제한과 관련된 내용이나 일치 항목이 잘리지 않는다는 것을 보장하는 내용을 찾을 수 없습니다.
나는 이것이 이상하다고 생각하며 이 동작에 대한 "수정"은 물론 설명도 찾지 못했습니다.
따라서 질문은 다음과 같습니다. 배열 매개변수 확장 내부의 패턴 일치를 통해 위의 예상 결과를 얻을 수 있는 방법이 있습니까?
답변1
# Expected: declare -a c=([0]="kek") # Got: declare -a c=([0]="k")
나는 이것을 다음과 같이 단순화할 수 있다고 생각합니다.
$ var="abcd"
$ echo "${var/!(abcd)/}"
d
그리고 나생각하다var="abbbcd"; echo "${var/a+(b)/}"
일어나는 일은 prints 와 비슷합니다 cd
. 쉘은 a+(b)
문자열의 시작 부분에서 시작하여 가장 긴 일치 항목을 찾는 패턴과 일치하는 항목을 찾으려고 시도합니다. abbbcd
또는 abbbc
일치하지 않지만 abbb
일치하고 해당 부분이 제거됩니다.
(또는 시작해서 a
하위 패턴과 일치하는 것을 보고 a
계속해서 전체 패턴과 일치하는 것을 볼 수도 있지만 일치하지 않기 때문에 ab
가장 오래 일치하는 것입니다.)abb
abbb
abbbc
abbb
마찬가지로, 패턴의 경우 !(abcd)
전체 abcd
문자열아니요일치하지만 하위 문자열은 abc
일치합니다. 삭제되었으며 왼쪽 d
.
또는 귀하의 경우 kek
에는아니요일치 !(kek)
하지만 ke
일치합니다. 유지하십시오 k
.
비슷하게:
$ var="abcd"
$ echo "${var//!(a*)/}"
a
전체 문자열이 abcd
일치하지 않고 !(a*)
첫 번째 문자로 시작하는 항목도 일치하지 않으므로 a
일치자는 두 번째 문자부터 계속 시작합니다. bcd
일치 !(a*)
하여 삭제되었습니다.
이는 직관적이지 않은 것처럼 보일 수 있지만 문자열의 어느 위치에서든 일치하는 항목이 계산되는 다른 모든 경우와 유사합니다. 예를 들어 문자열의 중간 부분 과 일치하는 b*e
문자열의 패턴을 시도해 보세요. 단지 부정적인 패턴의 경우 일치하는 문자열이 크게 다를 수 있습니다.abcdefg
bcde
어쨌든, "필터" 기능과 같은 더 나은 데이터 구조 도구를 갖춘 다른 프로그래밍 언어를 사용하는 것이 더 나을 수도 있습니다.
또한 필터링 아이디어에는 다소 유용하지만 c=(${dicerolls[@]/!(kek)/});
따옴표가 없는 확장은 배열 요소에 공백이나 와일드카드가 포함된 경우 문제를 일으킬 수 있습니다. 적절한 "필터" 기능에는 그러한 문제가 없습니다.