zsh 배열의 모든 요소에 하위 문자열 확장을 적용할 수 있습니까?

zsh 배열의 모든 요소에 하위 문자열 확장을 적용할 수 있습니까?

배열의 모든 요소에서 처음 2개와 마지막 3개 문자를 제거하고 싶다고 가정해 보겠습니다.

results=( QK9H9UtADCgnG AlaLkCADjQ krsxseW8H1VrU 6nBG94ZbCWQ )

나는 끝내고 싶다

results=( 9H9UtADC aLkCA sxseW8H1 BG94Zb )

요소를 반복 하고 하위 문자열 확장이 배열 대신 각 요소에 영향을 미치 도록 사용하는 것 외에 ${element:2:-3}유사한 작업을 수행할 수 있는 플래그 또는 일부 조합이 있습니까 ?${(⭕)results:2:-3}


중요한 경우 내 특별한 경우에는 배열이 작동합니다.안 돼요빈 요소가 있습니다. 요소는 다음과 같습니다.아니요모든 종류의 공백 문자를 포함하며 추출 규칙은 항상왼쪽>P+S그건모든 요소의 길이는 항상 요소의 총 길이보다 깁니다.에스접미사 합계삭제하려는 내용을 수정하세요.
저는 문자열을 수정하고 텍스트 처리 도구를 사용하는 데 관심이 없습니다. 위에서 말했듯이 현재 루프 스루 기능을 사용하고 있으므로 입력을 줄이려는 문제가 아니며 매뉴얼을 살펴 보았지만 할 수 없기 때문에 이것이 가능한지 궁금합니다. 이를 수행하는 방법을 찾으십시오.

답변1

ksh93에서 오는 것은 ${string:offset:length}zsh에 기본이 아니며 ksh93/bash와의 호환성을 위해 최근에 추가되었습니다.

zsh에서는 이 작업을 수행하는 것이 좋습니다 $string[first,last](ksh93 이전).

그러나 어쨌든 zsh이든 $var[first,last]ksh93-style ${var:offset:length}이든 이들은 문자열과 배열에 적용할 수 있는 연산자입니다(bash/ksh와 달리 zsh에서는 배열과 스칼라가 두 개의 별도 변수 유형이므로 연산자를 다른 방식으로 적용할 수 있습니다). ), 첫 번째 경우에는 하위 문자열을 제공하고 두 번째 경우에는 요소의 하위 집합을 제공합니다.

내가 아는 한, 이것이 전체 배열 대신 각 문자열 요소에 적용될 것이라고 zsh에 알릴 수 없습니다.

${results[1][3,-4]}(또는 ${results[1]:2:-3})은 작동하지만 문자열이 아닌 배열을 생성 ${results[1,2][3,-4]}하지 않으므로 배열로 적용됩니다.${results[1,2]}[3,-4]

그러나 여기서는 다른 접근 방식을 취할 수 있습니다.

예를 들어, 각 요소에 ${string#pattern}및 ksh 스타일 연산자를 적용할 수 있습니다.${string%pattern}

results=( ${${results#??}%???} )

또는 선행 및 후행 문자를 원하는 만큼 제거하세요.

set -o extendedglob
results=( ${${results#?(#c5)}%?(#c8)} )

ksh93 스타일을 사용하여 각 요소를 임의로 수정할 수도 있습니다 ${array/pattern/replacement}. 예를 들면 다음과 같습니다.

set -o extendedglob
results=( ${results/(#m)*/$MATCH[3,-4]} )

당신은 또한 볼 수 있습니다

results=( ${results/(#b)??(*)???/$match[1]} )

이렇게 하면 5자 이상의 요소만 수정됩니다( results=( "${results[@]/??@(*)???/\1}" )ksh93과 동일).

또 다른 복잡한 접근 방식:

() { results=( ${(e)argv} ); } '${results['{1..$#results}'][3,-4]}'

${results[1][3,-4]} ${results[2][3,-4]}우리 는 플래그를 사용하여 e이를 평가하고 배열에 다시 할당하는 익명 함수에 etc를 전달합니다 .

[@](이 모든 것 중에서 가지치기 후에 비어 있는 요소를 포함하여 빈 요소를 유지하려면 with 및 따옴표를 사용하세요.)

답변2

배열 요소를 자르는 한 가지 방법은 다음과 같습니다.

trimmed_array=( $(printf '%s\n' "${results[@]}" | cut -c 3- | rev | cut -c 4- | rev) )

새 어레이를 확인하십시오.

printf '%s\n' "${trimmed_array[@]}"
9H9UtADC
aLkCA
sxseW8H1
BG94Zb

각 파이프 섹션의 동작을 쉽게 검사하고 이해할 수 있습니다.

관련 정보