Bash 5.0.17 (1)을 사용하는 원격 CentOS에서 SSH를 통해 내가 실행 한 유일한 사용자 인 경우 read web_application_root
:
$HOME/www
또는 다음과 함께 :
${HOME}/www
또는 다음과 함께 :
"${HOME}"/www
또는 다음과 함께 :
"${HOME}/www"
.NET과 같은 확장 된 (환경) 변수를 사용하여 출력을 얻는 것을 목표로합니다 MY_USER_HOME_DIRECTORY/www
.
ls -la $HOME/www
잘 작동 하지만 ls -la $web_application_root
모든 예제 에서 실패합니다. 오류 예는 다음과 같습니다.
ls: cannot access '$HOME/www': No such file or directory
나는 read
위의 모든 $HOME
변형을 (오류의 작은 따옴표로 인해) 문자열로 취급 하므로 확장하지 않는다는 것을 이해합니다.
읽기 내에서 변수를 확장하는 방법은 무엇입니까?
당신이 확장합니다 $VAR
s 또는 ${VAR}
S VAR
(이름이 시작하는 ASCII 문자 또는 밑줄 및 다음 ASCII의 alnums 또는 밑줄으로 제한) 기존 환경 변수의 이름을 의미하고 (다른 모든 단어 확장을 떠나 $non_exported_shell_variable
, $1
, $#
, ${HOME+x}
, $((1 + 1))
, $(cmd)
...)의 손길이 닿지 않은, 당신은 사용할 수 있습니다 envsubst
(GNU에서 gettext
) :
IFS= read -r web_application_root || exit
web_application_root=$(printf %s "$web_application_root" | envsubst)
ls -la -- "$web_application_root"
변수 이름을 인수로 사용하고 읽기 및 환경 변수 확장을 모두 수행하는 쉘 함수로 만들 수 있습니다.
read_one_line_and_expand_envvars() {
IFS= read -r "$1"
ret="$?"
command eval "$1"'=$(printf %s "${'"$1"'}" | envsubst)' && return "$ret"
}
예를 들어 다음과 같이 사용됩니다.
printf >&2 'Please enter the root dir (${ENVVAR} expanded): '
read_one_line_and_expand_envvars web_application_root || exit
printf >&2 'The expanded version of your input is "%s"\n' "$web_application_root"
제한된 환경 변수 세트로 대체를 제한하려면 목록을 $VAR1$VAR2...
리터럴 인수로 envsubst
다음 과 같이 전달합니다 .
web_application_root=$(
printf %s "$web_application_root" |
envsubst '$HOME$MYENVVAR'
)
(여기 알려줍니다 envsubst
만 대신에 $HOME
, ${HOME}
, $MYENVVAR
그리고 ${MYENVVAR}
다른 모든 떠나, 입력에서 $VAR
의 손길이 닿지 않은들).
모든 형태의 단어 확장 ¹을 허용하려는 경우 (그러나 명령 삽입 취약점이됩니다) 다음을 수행 할 수 있습니다.
web_application_root=$(eval "cat << __EOF__
$web_application_root
__EOF__")
또는 변수 이름을 인수로 사용하는 함수로 :
read_one_line_and_perform_shell_word_expansions() {
IFS= read -r "$1"
ret=$?
command eval '
case "${'"$1"'}" in
(EOF) ;;
(*)
'"$1"'=$(command eval "cat << EOF
${'"$1"'}
EOF")
esac' && return "$ret"
}
printf >&2 'Please enter the root dir ($var/$((...))/$(cmd) allowed): '
read_one_line_and_perform_shell_word_expansions web_application_root || exit
printf >&2 'The expanded version of your input is "%s"\n' "$web_application_root"
자세한 인라인 문서와 동일한 기능 :
read_one_line_and_perform_shell_word_expansions() {
# first argument of our function is the variable name or REPLY
# if not specified.
varname=${1-REPLY}
# read one line from stdin with read's unwanted default post-processing
# (which is otherwise dependant on the current value of $IFS) disabled.
IFS= read -r "$varname"
# record read's exit status. If it's non zero, a full line could not be
# read. We may still want to perform the expansions in whatever much
# was read, and pass that exit status to the caller so they decide what
# to do with it.
ret=$?
# We prefix the "eval" special builtin with "command" to make it lose
# its "special" status (namely here, exit the script about failure,
# something bash only does when in standard mode).
command eval '
# the approach we take to expand word expansions would be defeated
# if the user entered "EOF" which is the delimiter we chose for our
# here-document, so we need to handle it as a special case:
case "${'"$varname"'}" in
(EOF) ;;
(*)
# the idea here is to have the shell evaluate the
# myvar=$(command eval "cat << EOF
# ${myvar}
# EOF")
#
# shell code when $1 is myvar, so that the
#
# cat << EOF
# contents of $myvar with $(cmd), $ENV and all
# EOF
#
# shell code be evaluated, and those $(cmd), $ENV expansions
# performed in the process
'"$varname"'=$(command eval "cat << EOF
${'"$varname"'}
EOF")
esac' &&
# unless eval itself failed, return read's exit status to the caller:
return "$ret"
}
그러나 당신의 문제는 XY 문제처럼 들립니다. 입력을받는 read
것은 번거롭고 비현실적입니다. 이 인수를 통해 입력을 얻기 위해 더 나은, 그리고 당신은으로 확장 할 호출자의 쉘에 둘 수 있습니다 그들이 그것을 계획입니다.
대신에
#! /bin/sh -
IFS= read -r var
ls -l -- "$var"
(그리고 기억 호출 read
없이 IFS=
및없이하는 것은 -r
거의 절대 당신이 원하는 없습니다 ).
그것을 만드십시오 :
#! /bin/sh -
var=${1?}
ls -l -- "$var"
그리고 호출을 수행 할 수 있습니다 your-script ~/dir
하거나 your-script "$HOME/dir"
또는 your-script '$$$weird***/dir'
심지어 your-script $'/dir\nwith\nnewline\ncharacters'
그들이 맞는 볼.
¹ 이 문맥에서 단어 확장 은 매개 변수 확장 , 산술 확장 및 명령 대체를 의미 합니다. 여기에는 파일 이름 생성 (일명 globbing 또는 경로 이름 확장 ), 물결표 확장 또는 중괄호 확장 (그 자체는 표준 sh
기능이 아님)이 포함 되지 않습니다 . here-document를 사용하면 '
및 "
s가 그대로 유지되지만 여전히 백 슬래시 처리가 있음을 유의하십시오.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다