Bash - 배열을 변수에 문자열로 할당

Bash - 배열을 변수에 문자열로 할당

이 코드가 있고 올바른 결과가 인쇄되지만 마지막 줄의 에코를 변수로 가져오는 방법을 모르겠습니다.

# hostname is 'tech-news-blog-324344' . Setting it into array host_name_array
IFS='-' read -r -a host_name_array <<< "$(hostname)" 
#removing the last part of string after last "-"
unset 'host_name_array[${#host_name_array[@]}-1]'
( IFS=$'-'; echo "${host_name_array[*]}" )  
#result is 'tech-news-blog'

마지막 행의 값을 변수에 어떻게 넣을 수 있나요? 나는 다음을 시도했습니다 :

( IFS=$'-'; URL="${host_name_array[*]}" )

그러나 내가 얻은 결과는 "-" 대신 어레이 사이에 공백이 있는 "Technology News Blog"입니다.

답변1

런타임 시 IFS='-' read -r -a host_name_array <<< "$(hostname)"배열은 (tech news blog 324344).

마지막 요소를 삭제한 후 unset 'host_name_array[${#host_name_array[@]}-1]'배열은 입니다 (tech news blog).

따라서 echo 를 얻으려면 다음 tech-news-blog과 같이 일부 대체가 이루어져야 합니다 .echo "${host_name_array[*]}"tech news blog

tr과 함께:echo "${host_name_array[*]}" | tr ' ' '-'

sed:echo "${host_name_array[*]}" | sed 's/ /-/g'

답변2

다음과 같이 구분된 요소를 출력한 다음 -매개변수 확장을 통해 마지막 요소를 제거하여 이를 수행할 수 있습니다.-

$ var=$(printf '%s-' "${host_name_array[@]}")

$ echo "$var"
foo-bar-spam-egg-

$ var="${var%-}"

$ echo "$var"
foo-bar-spam-egg

또한 요소가 첫 번째 문자로 구분되어 전체적으로 출력되는 것을 ${host_name_array[@]}방지 해야 합니다 .${host_name_array[*]}IFS


간단한 매개변수 확장을 통해 원하는 결과를 얻을 수 있습니다.

${var%-*}

예:

$ var=$(hostname)

$ echo "${var%-*}"

답변3

(...)서브쉘을 소개합니다. 따라서 $URL그 이후에는 설정되지 않습니다(여전히 하위 쉘의 이전 값이 유지됩니다). 당신이 원하는 것:

IFS=-
read -r -a host_name_array <<< "$(hostname)" 
unset 'host_name_array[${#host_name_array[@]}-1]'
URL="${host_name_array[*]}"

"${host_name_array[*]}"$IFS표준과 마찬가지로 "$*"배열의 요소를 첫 번째 문자에 연결합니다 sh.

$IFS서브쉘을 사용하는 이유가 전역적으로 수정하고 싶지 않기 때문이라면 $IFS로컬 범위가 지정된 함수에서 이를 수행할 수 있습니다.

f() {
  local IFS=-
  ...
}
f

또는 명령 대체를 사용하여 하위 쉘을 생성하지만 데이터가 상위 쉘로 전달되도록 허용합니다.

URL=$(IFS=-; printf '%s\n' "${host_name_array[*]}")

그러나 여기서는 표준 sh확장을 사용하여 후행 구성 요소를 제거하겠습니다.

URL=$(uname -n) # uname -n is the standard equivalent of hostname
URL=${URL%-*}

위와 비교하면 다음과 같은 장점이 있습니다.

  • 텍스트에 개행 문자가 포함된 경우에도 작동합니다(여기서는 호스트 이름에서는 그럴 가능성이 낮지만).
  • 텍스트가 포함되지 않으면 -아무것도 삭제되지 않습니다.
  • 더 효율적입니다. read <<< $(hostname)run 을 의미하고 hostname, 파이프를 통해 출력을 읽고, 임시 파일에 저장하고, read해당 파일의 첫 번째 줄을 읽습니다.
  • 이러한 임시 변수를 사용하여 변수 네임스페이스를 파괴하지 않습니다.
  • 더 짧습니다.
  • 휴대용입니다. bash코드를 실행하기 위해 설치가 필요하지 않습니다 . 시스템 sh이면 충분합니다.

어떤 경우 에라도,변수를 인용하는 것을 잊지 마세요목록 컨텍스트에서 사용하는 경우:

printf '%s\n' "$URL"

할 때:

$URL 에코

분할+글로브 연산자를 호출하고 있습니다. 따라서 $IFS여전히 포함되어 -있으면 $URL분할되어 -공백 echo으로 구분된 단어가 출력됩니다.

답변4

구체적인 답변 : 채찍포크!

이것은 이미 bashism을 사용하고 있거나 sed다른 tr외부 도구는 쓸모가 없기 때문에:

IFS='-' read -r -a host_name_array < <(hostname)
#removing the last part of string after last "-"
unset host_name_array[${#host_name_array[@]}-1]

shorted=${host_name_array[*]}
echo ${shorted// /-}

아니면 더 간단합니다:

이는 더 짧고 빠르며 간단합니다.

read myvar < <(hostname)
echo ${myvar%-*}

host_name_array다른 이유로 필요한 경우 :

read shorted < <(hostname)
host_name_array=(${shorted//-/ })
shorted=${shorted%-*}

그래서 당신은 배열을 가지고 있습니다그리고짧은 호스트 이름:

declare -p host_name_array shorted

다음과 유사한 내용이 반환됩니다.

declare -a host_name_array='([0]="tech" [1]="news" [2]="blog" [3]="324344")'
declare -- shorted="tech-news-blog"

관련 정보