Bash는 배열을 반복하고 비어 있는지 감지합니다.

Bash는 배열을 반복하고 비어 있는지 감지합니다.

null문자열 또는 문자열 배열일 수 있는 변수를 반복하려고 합니다 .

ZEIT_DEPLOYMENT_ALIASES=null또는ZEIT_DEPLOYMENT_ALIASES=['domain.sh]

나는 bash의 초보자이고 읽었습니다.bash는 비어 있지 않은 한 파일 목록을 반복합니다.하지만 이해가 안 돼요.

나는 두 가지 다른 접근 방식을 시도했습니다.

값은 ZEIT_DEPLOYMENT_ALIASES실제로 jqJSON을 읽는 라이브러리에서 가져옵니다.

ZEIT_DEPLOYMENT_ALIASES=$(cat now.$CUSTOMER_REF_TO_DEPLOY.staging.json | jq --raw-output '.alias')

방법 1

  ZEIT_DEPLOYMENT_ALIASES=['test.sh']

  # Check if there are no aliases configured
  if [ -z "$ZEIT_DEPLOYMENT_ALIASES" ]
  then
    ZEIT_DEPLOYMENT_ALIASES_COUNT=${#ZEIT_DEPLOYMENT_ALIASES[@]}
    echo "$ZEIT_DEPLOYMENT_ALIASES_COUNT alias(es) found. Aliasing them now..."

    # For each alias configured, then alias it to the deployed domain
    for DEPLOYMENT_ALIAS in "${ZEIT_DEPLOYMENT_ALIASES_COUNT[@]}"
    do
      echo "npx now alias "$ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS
      npx now alias $ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS --token $ZEIT_TOKEN || echo "Aliasing failed for '$DEPLOYMENT_ALIAS', but the build will continue regardless."
    done
  else
    # $ZEIT_DEPLOYMENT_ALIASES is null, this happens when it was not defined in the now.json file
    echo "There are no more aliases to configure. You can add more aliases from your now.json 'alias' property. See https://vercel.com/docs/configuration?query=alias%20domain#project/alias"
    echo "$ZEIT_DEPLOYMENT_ALIASES"
  fi

하지만 이것조차 약관 ZEIT_DEPLOYMENT_ALIASES=['something']에 들어 가지 않습니다 .then

방법 2

ZEIT_DEPLOYMENT_ALIASES=['test.sh']
echo "Alias(es) for current project:" $ZEIT_DEPLOYMENT_ALIASES

for DEPLOYMENT_ALIAS in $ZEIT_DEPLOYMENT_ALIASES; do
  [ -z "$DEPLOYMENT_ALIAS" ] || continue
  echo "npx now alias "$ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS
  npx now alias $ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS --token $ZEIT_TOKEN || echo "Aliasing failed for '$DEPLOYMENT_ALIAS', but the build will continue regardless."
done

다시 말하지만, [ -z "$DEPLOYMENT_ALIAS" ]항상 true.

원한다면 놀이터는 다음과 같습니다.

  1. https://www.jdoodle.com/iembed/v0/3bs
  2. https://www.jdoodle.com/iembed/v0/3bo

답변1

이 파일이 주어지면:

$ cat test.json
{"alias": ["foo", "bar"], "whatever": "xyzzy"}

적어도 내 버전은 jq이 출력을 제공합니다.jq --raw-output '.alias[]' < test.json

$ jq --raw-output '.alias[]' < test.json
foo
bar

즉, 항목이 서로 다른 줄에 있습니다. 이를 사용하여 항목을 서로 구분할 수 있기 때문에 이는 중요합니다. 예를 readarray들어 <(...),프로세스 교체, 이는 명령의 출력을 파일처럼 사용할 수 있게 하여 < <(...)표준 입력에서 사용할 수 있게 합니다. 실제로 파이프가 서브쉘을 실행한다는 점을 제외하면 파이프와 약간 비슷하므로 파이프 이후에 읽은 값을 사용할 수 없습니다. )

#!/bin/bash
readarray -t entries < <(jq  '.alias[]' < test.json)
if [ "${#entries[@]}" = 0 ]; then
    echo empty array...
fi

# this will not do anything if the array is empty
for entry in "${entries[@]}"; do
    echo "processing entry $entry..."
done

alias누락 가능성이 있는 필드를 처리하려면 대신 .alias[]?in을 사용하세요 jq. 그러나 이는 {"alias": "foo"}배열이 아닌 문자열 값(예:)을 null로 처리하므로 가능하다면 다른 작업을 수행해야 합니다.

또한 항목에 개행 문자가 포함되어 있으면 --raw-output그대로 인쇄되므로 개행 문자가 포함된 항목은 마치 여러 개의 개별 항목인 것처럼 여러 줄에 걸쳐 분할되어 표시됩니다.


또는 프로세스 대체가 필요하지 않으므로 Bash뿐만 아니라 표준 셸에서도 작동해야 합니다.

#!/bin/sh
jq --raw-output '.alias[]' < json.txt | 
(
any=
while IFS= read -r line; do 
    echo "doing something with '$line'..."
    any=1
done
if [ "$any" != 1 ]; then
    echo "empty input..."
fi
)

바라보다내 변수가 하나의 "읽는 동안" 루프에서는 로컬이지만 겉보기에 유사한 다른 루프에서는 로컬이 아닌 이유는 무엇입니까?괄호가 필요한 이유에 대해.


이제 코드에 대해:

ZEIT_DEPLOYMENT_ALIASES=['test.sh']

그러면 문자열이 [test.sh]변수에 할당됩니다. 이는 ["test.sh"]에서 가져온 문자열을 할당하는 것과 다릅니다 jq. 왜냐하면 여기에서 쉘이 사용자가 제공한 따옴표를 처리하기 때문입니다. 명령 대체의 출력을 기반으로 유사하게 처리되지 않습니다. 이는 배열이 아닌 단일 스칼라 변수이기도 합니다.

if [ -z "$ZEIT_DEPLOYMENT_ALIASES" ]

이는 문자열이 빈 문자열인지 테스트하는데, 이는 아마도 의도한 바가 아닐 것입니다. 어쨌든, jq.alias수 있어 null, 이는 빈 문자열과 다릅니다.

${#ZEIT_DEPLOYMENT_ALIASES[@]}

1이는 배열이 아니기 때문에 항상 그렇습니다 . 같은 이유로 for루프는 원하는 대로 작동하지 않습니다.

Bash는 JSON 자체를 처리하지 않습니다. 명령 대체에서 문자열을 가져오면 ["foo", "bar"]이는 단지 JSON입니다.. 개별 항목으로 직접 분할해야 합니다...

답변2

#1을 시도해 볼 수 있는 솔루션은 다음과 같습니다.

그만한 가치가 있기 때문에 null이것은 empty내 초기 생각과 다르지 않은 까다롭습니다.

가장 어려운 것은 다음 jq을 사용하여 JSON 배열을 bash 배열로 변환하는 것입니다.

readarray -t ZEIT_DEPLOYMENT_ALIASES < <(jq --raw-output '.alias[]' < now.$CUSTOMER_REF_TO_DEPLOY.staging.json)

매우 감사합니다https://unix.stackexchange.com/a/615717/60329

  ZEIT_DEPLOYMENT_ALIASES_JSON=$(cat now.$CUSTOMER_REF_TO_DEPLOY.staging.json | jq --raw-output '.alias')
  echo "Custom aliases: " $ZEIT_DEPLOYMENT_ALIASES_JSON

  # Convert the JSON array into a bash array - See https://unix.stackexchange.com/a/615717/60329
  readarray -t ZEIT_DEPLOYMENT_ALIASES < <(jq --raw-output '.alias[]' < now.$CUSTOMER_REF_TO_DEPLOY.staging.json)

  # Check if there are no aliases configured (it will return "null" in such case, which is not the same as bash "empty")
  if [ "$ZEIT_DEPLOYMENT_ALIASES" != null ]
  then
    ZEIT_DEPLOYMENT_ALIASES_COUNT=${#ZEIT_DEPLOYMENT_ALIASES[@]}
    echo "$ZEIT_DEPLOYMENT_ALIASES_COUNT alias(es) found. Aliasing them now..."

    # For each alias configured, then assign it to the deployed domain
    for DEPLOYMENT_ALIAS in "${ZEIT_DEPLOYMENT_ALIASES[@]}"; do
      echo "npx now alias "$ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS
      npx now alias $ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS --token $ZEIT_TOKEN || echo "Aliasing failed for '$DEPLOYMENT_ALIAS', but the build will continue regardless."
    done
  else
    # $ZEIT_DEPLOYMENT_ALIASES is null, this happens when it was not defined in the now.json file
    echo "There are no more aliases to configure. You can add more aliases from your now.json 'alias' property. See https://vercel.com/docs/configuration?query=alias%20domain#project/alias"
    echo "$ZEIT_DEPLOYMENT_ALIASES"
  fi

감사합니다!

관련 정보