POSIX 쉘 스크립트에서 의사 배열을 사용하는 방법은 무엇입니까?

POSIX 쉘 스크립트에서 의사 배열을 사용하는 방법은 무엇입니까?

POSIX 쉘 스크립트에서 의사 배열을 사용하는 방법은 무엇입니까?

Bash 스크립트에서 10개의 정수 배열을 다음으로 바꾸고 싶습니다.무엇POSIX 쉘 스크립트와 유사합니다.

나는 우연히 만날 수 있었다Rich의 sh(POSIX 쉘) 트릭, 단면에배열 사용.

내가 시도한 것:

save_pseudo_array()
{
    for i do
        printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
    done
    echo " "
}

coords=$(save_pseudo_array "$@")
set -- 1895 955 1104 691 1131 660 1145 570 1199 381
eval "set -- $coords"

이해가 안 돼요. 그게 문제인데, 누군가 설명해 주시면 정말 감사하겠습니다.

답변1

기본 아이디어는 set배열에서 인덱스 값으로 작업하는 경험을 재현하는 것입니다. 따라서 배열로 작업하려면 set다음과 같은 값을 사용하세요.

set -- 1895 955 1104 691 1131 660 1145 570 1199 381

$1그런 다음 $2등을 사용하여 for주어진 값을 처리 할 수 있습니다 .

여러 배열이 필요한 경우에는 이 모든 것이 별로 유용하지 않습니다. 이것이 save바로 eval트릭이 들어오는 곳입니다.리치 save기능1 현재 위치 인수를 처리하고 적절한 참조가 포함된 문자열을 출력합니다. 그런 다음 eval저장된 값을 복원하는 데 사용할 수 있습니다. 그럼 넌 도망쳐

coords=$(save "$@")

현재 작업 중인 배열을 저장한 coords다음 새 배열을 만들어 사용하고, 다시 사용해야 할 경우 다음을 수행할 coordseval있습니다.

eval "set -- $coords"

coords이 예를 이해하려면 두 개의 배열, 즉 에 저장하려는 이전에 설정된 값이 있는 배열과 1895, 955 등을 포함하는 배열 로 작업하고 있다는 점을 고려해야 합니다 . 코드 조각 자체는 그다지 중요하지 않습니다. 그 자체로는 set및 행 eval사이에서 일부 처리를 수행 해야 합니다 . 나중에 1895, 955 어레이를 반환해야 하는 경우 복원하기 전에 어레이를 저장하십시오 coords.

newarray=$(save "$@")
eval "set -- $coords"

이렇게 하면 $newarray나중에 복원할 수 있습니다.


1은 다음과 같이 정의됩니다.

save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}

답변2

아이디어는 임의의 문자열 목록을 나중에 목록이나 임의의 문자열을 재구성하는 데 사용할 수 있는 형식의 스칼라 변수로 인코딩하는 것입니다.

 $ save_pseudo_array x "y z" $'x\ny' "a'b"
'x' \
'y z' \
'x
y' \
'a'\''b' \

$

set --앞에 지속하면 x문자열 목록을 재구성하고 배열 y z에 저장하는 셸 코드를 생성하므로 이를 사용하기만 하면 됩니다.$@eval

sed각 문자열을 올바르게 인용하는 일을 담당합니다 (첫 번째 줄의 시작 부분, 마지막 줄의 끝 부분에 모든 을 '추가하고 교체 ).''\''

그러나 이는 각 인수에 대해 하나의 printf명령을 실행하는 것을 의미하므로 sed다소 비효율적입니다. 이는 awk를 한 번만 호출하여 보다 직접적인 방법으로 수행할 수 있습니다.

save_pseudo_array() {
  LC_ALL=C awk -v q=\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q "\\" q q, ARGV[i])
        printf "%s ", q ARGV[i] q
      }
      print ""
    }' "$@"
}

관련 정보