배열이 있습니다.
CATEGORIES=(one two three four)
매개변수 확장을 사용하여 각 배열 구성원 앞에 다음을 추가할 수 있습니다.
echo ${CATEGORIES[@]/#/foo }
같은 방법으로 각 배열 멤버에 추가할 수 있습니다.
echo ${CATEGORIES[@]/%/ bar}
어떻게 둘 다 가질 수 있나요? 다음 중 어느 것도 작동하지 않습니다.
echo ${CATEGORIES[@]/(.*)/foo \1 bar}
echo ${CATEGORIES[@]/(.*)/foo $1 bar}
echo ${CATEGORIES[@]/(.*)/foo ${BASH_REMATCH[1]} bar}
답변1
최종 목표에 따라 다음을 사용할 수 있습니다 printf
.
$ a=(1 2 3)
$ printf "foo %s bar\n" "${a[@]}"
foo 1 bar
foo 2 bar
foo 3 bar
printf
형식 문자열은 모든 인수가 사용될 때까지 재사용되므로 문자열 집합에 일부 형식을 적용하는 쉬운 방법을 제공합니다.
답변2
기록의 경우 with 배열 요소에 중괄호와 같은 확장을 여는 연산자가 zsh
있습니다 . ${^array}
그래서:
$ a=(one two three)
$ b=('foo '${^a}' bar')
$ printf '<%s>\n' $b
<foo one bar>
<foo two bar>
<foo three bar>
검색 및 바꾸기도 에서 작동합니다 zsh
.
$ printf '<%s>\n' ${a//(#m)*/foo $MATCH bar}
<foo one bar>
<foo two bar>
<foo three bar>
그리고 printf -v
배열에서:
$ b=(); printf -v b 'foo %s bar' "$a[@]"
$ printf '<%s>\n' $b
<foo one bar>
<foo two bar>
<foo three bar>
echo ${CATEGORIES[@]/(.*)/foo \1 bar}
작성된 경우 ksh93
:
$ printf '<%s>\n' "${CATEGORIES[@]/@(.*)/foo \1 bar}"
<foo one bar>
<foo two bar>
<foo three bar>
답변3
p='* "foo '
s=' bar $USER'
CATEGORIES=(one two three four)
CATEGORIES=("${CATEGORIES[@]/#/$p}")
CATEGORIES=("${CATEGORIES[@]/%/$s}")
paste <(printf '[%s]\n' "${!CATEGORIES[@]}") \
<(printf '%s\n' "${CATEGORIES[@]}")
산출:
[0] * "foo one bar $USER
[1] * "foo two bar $USER
[2] * "foo three bar $USER
[3] * "foo four bar $USER
답변4
이것은특별한 경우추가된(또는 앞에 추가된) 문자열이 다음과 같은 경우에 적합한 솔루션은 다음과 같습니다.단일 문자, 새 배열의 값이 필요하지 않습니다.
array=( aa bb cc )
IFS="]" # or, IFS="["
echo "${array[*]/#/ [}$IFS" # or, echo "$IFS${array[*]/%/] }
출력을 생성합니다 [aa] [bb] [cc]
.
- 인용된 형식은
"${array[*]}"
각 쌍 사이에 구분 기호를 추가합니다(제약조건이 나타나는 위치인 의 첫 번째 문자).]
IFS
${array[*]/#/ [}
[
각 요소 앞에 추가 (또는/%/
양식 추가)- 마지막으로 확장된 값에 후행
]
(from )을 추가합니다.IFS
이 단계를 하나씩 적용하면 다음과 같은 결과를 얻을 수 있습니다.
aa]bb]cc
[aa] [bb] [cc
[aa] [bb] [cc]
(데이터를 새 어레이로 쉽게 복원할 수도 있습니다.만약에이 값에는 공백이 포함되어 있지 않습니다. )
한 줄에서 다양한 접두사/접미사 작업을 수행할 수 있습니다.
for ii in "${array[@]/#/foo }"; do echo "${ii/%/ bar}"; done
printf
다음은 새 어레이에 복사하는 보다 강력한 솔루션입니다 .
mapfile -d '' newarray < <(printf "foo %s bar\0" "${array[@]}")
서브 쉘을 희생하더라도 ( bash-4.4 필요 mapfile -d
)
마지막으로 새 배열에 복사하고 필요한 경우 희소 배열과 연관 배열을 처리할 수도 있는 루프 변형이 있습니다.
declare -a array newarray # -a for indexed array, -A for associative
array=( one two three )
for ii in "${!array[@]}"; do
printf -v "newarray[$ii]" "foo %s bar" "${array[$ii]}"
done
( printf
필수는 아니지만 직접 할당할 수 있지만 IMHO가 더 명확합니다. bash
(아직!) 그러나 배열로 인쇄를 지원하면 zsh
루프 없는 복사 및 단일 라인 변환이 가능합니다. 위의 Stéphane 답변을 참조하세요.)
여기서 유용한 점은 확장의 일치 문자열에 대한 자리 표시자로 bash
제네릭이 지원되는 경우 &
(예: $MATCH
) 입니다.zsh
코드는 거기 있어요(그리고 오랫동안 사용해 왔지만) 안타깝게도 아직 활성화되지 않았습니다( shouldexp_replacement()
참조subst.c
). 활성화하면( #if 0
두 번 변경한 후 다시 컴파일) 예상대로 작동합니다.
array=( aa bb cc )
newarray=( "${array[@]/*/foo & bar}" )
그렇군요. 다음 버전에서는 가능할 수도 있겠네요...
compgen
접두사/접미사 작업이 있습니다(지원되지만 &
여기서 사용할 수 있는 방식은 아닙니다). 우리가 할 수 있는 최선은 Mulu의 printf
솔루션보다 더 나쁩니다.
compgen -P "foo " -S " bar" -W "${array[*]}"
( -W
단 하나의 옵션만 필요하므로 배열이 평면화되어 공백 등이 있는 값에 문제가 발생한다는 점에 유의하세요 IFS
)