bash - 배열의 각 항목 앞에 요소를 추가합니다.

bash - 배열의 각 항목 앞에 요소를 추가합니다.

grep다른 프로그램의 출력에서 ​​제외하려는 문자열이 포함된 배열이 있습니다. -e각 요소 앞에 하나씩 추가 해야 합니다 . 예를 들어:

exclude=("$0" /usr/sbin/crond)
needs-restarting | grep -Fwiv "${exclude[@]}"

이제 이 경우 다음과 같이 각 요소 앞에 추가 --regexp=(또는 그냥 )할 수 있다는 것을 알았습니다.-eexclude=( "${exclude[@]/#/--regexp=}" )

하지만 일반적으로 어떻게 해야 합니까? 나는 이것을 알아 냈지만 아마도 더 쉬운 방법이있을 것입니다.

i=0
for elem in "${exclude[@]}"; do
  exclude[i]='-e'
  exclude[i+1]="$elem"
  ((i+=2))
done
declare -p exclude

답변1

4.4+ 에서는 bash다음을 수행할 수 있습니다.

readarray -td '' array < <(
  ((${#array[@]})) && printf -- '-e\0%s\0' "${array[@]}"
)

\0bash 변수는 어쨌든 NUL 바이트를 포함할 수 없기 때문에 이는 구분 기호로 사용됩니다 . 배열이 비어 있지 않을 것이라는 것을 알고 있다면 이것을 건너뛸 수 있습니다 ((${#array[@]})) &&.

예:

  • 앞으로:
    bash-5.0$ array=($'a\nb' '' 'c d' e)
    bash-5.0$ typeset -p array
    declare -a array=([0]=$'a\nb' [1]="" [2]="c d" [3]="e")
    
  • 뒤쪽에:
    bash-5.0$ typeset -p array
    declare -a array=([0]="-e" [1]=$'a\nb' [2]="-e" [3]="" [4]="-e" [5]="c d" [6]="-e" [7]="e")
    

에서는 zsh배열 압축 연산자를 사용할 수 있습니다.

opt=-e
(($#array == 0)) || array=("${(@)opt:^^array}")

아니면 이 복잡한 것:

set -o extendedglob # for (#m)
array=("${(Q@)"${(@z)array//(#m)*/-e ${(qq)MATCH}}"}")

-e <the-element-quoted>각 요소를 (플래그 사용)으로 바꾼 qq다음 z참조를 요소 목록으로 다시 구문 분석하고(합계가 -e분리됨 <the-element-quoted>) Q따옴표(및 @빈 요소를 유지하는 데 사용되는 따옴표 안의 요소(있는 경우))를 제거합니다. )).

답변2

제안된 루프를 약간 단순화할 수 있습니다.

exclude_args=()
for elem in "${exclude[@]}"; do
  exclude_args+=('-e' "$elem")
done
exclude=("${exclude_args[@]}")   # Optional, if you want to replace the original array's contents

관련 정보