예를 들어:
srcdir = ../libc # Src directory
prefix = /usr/local // Installation path
첫 번째 줄은 makefile에서 가져온 것이고 두 번째 줄은 config.make
.
쉘 스크립트의 $srcdir
변수 에 액세스해야 합니다 $prefix
.
` = `
내가 찾은 한 가지 해결책은 and 및 do `=`
이후의 모든 부분 을 잘라내는 것이었습니다 .#
//
eval
간단하고 안정적인 다른 솔루션이 있습니까?
나는 여기 있다 #!/bin/sh
.
답변1
쉘 스크립트에서 외국어를 구문 분석하려고 하면 절대 안 됩니다. 항상 예상치 못한 경고에 직면하게 되며 모든 것에 적응하려고 노력하는 것은 악몽이 될 뿐입니다.
대신, 네이티브 인터프리터를 사용하여 구문 분석하고 원하는 것을 제공하세요.
getmakevar() {
makefile="$1"
var="$2"
make getmakevar -f - <<EOI
include $makefile
getmakevar:
@echo \$($var)
EOI
}
이는 POSIX와 호환되며 가능한 모든 makefile 형식을 처리할 수 있습니다(유효한 gnu make인 경우).
# cat Makefile
bar=baz
myvar = /foo/$(bar)
# getmakevar Makefile myvar
/foo/baz
답변2
나는 순수한 POSIX sh 버전을 만들었습니다. 내가 좋아하는 점:
- 완전한 쉘 기반(printf를 제외하고 외부 명령이 호출되지 않음)
- 범용(쉘 함수 재사용 가능)
- 정의를 현재 환경으로 가져옵니다.
내가 싫어하는 것:
- 평가를 사용하세요. 피하려고 하는데 하드코딩하지 않고 정의하는 것이 필요하다. 이름이 의미가 있는지 확인하고 값을 참조하고 있습니다. 이것은 안전해야 하지만 100% 안전하다고 확신할 수는 없습니다.
- POSIX sh는 추악합니다.
- POSIX sh의 함수에는 지역 변수가 없습니다.
음, 여기 있습니다:
#!/bin/sh
trim_left() {
_str=$1 _chrs=$2
while [ "$_chrs" ]; do
_chr=${_chrs%"${_chrs#?}"}
while [ "${_str%"${_str#?}"}" = "$_chr" ]; do
_str=${_str#?}
done
_chrs=${_chrs#?}
done
printf %s "$_str"
}
trim_right() {
_str=$1 _chrs=$2
while [ "$_chrs" ]; do
_chr=${_chrs%"${_chrs#?}"}
while [ "${_str#"${_str%?}"}" = "$_chr" ]; do
_str=${_str%?}
done
_chrs=${_chrs#?}
done
printf %s "$_str"
}
trim_comment() {
_str=$1 _marker=$2
printf %s "${_str%%"$_marker"*}"
}
quote_str() {
_str=$1 _qstr=
while [ "$_str" ]; do
_chr=${_str%"${_str#?}"}
if [ "$_chr" = "'" ]; then
_qstr=$_qstr"'\\''"
else
_qstr=$_qstr$_chr
fi
_str=${_str#?}
done
printf "'%s'" "$_qstr"
}
# [a-zA-Z_][a-zA-Z_0-9]
valid_vname() {
_vname=$1
case $_vname in
[[:lower:][:upper:]_]*)
;;
*)
return 1
;;
esac
_vname=${_vname#?}
while [ "$_vname" ]; do
case $_vname in
[[:lower:][:upper:]_[:digit:]]*)
;;
*)
return 1
;;
esac
_vname=${_vname#?}
done
return 0
}
ws='
'
input_file=$1
[ "$input_file" ] || {
printf '%s\n' 'usage: script <file>' >&2;
exit 1
}
while IFS== read -r _name _value; do
name=$(trim_left "$(trim_right "$_name" "$ws")" "$ws")
case $_value in
*'#'*)
value=$(trim_comment "$_value" '#')
;;
*'//'*)
value=$(trim_comment "$_value" '//')
;;
esac
value=$(trim_left "$(trim_right "$value" "$ws")" "$ws")
if valid_vname "$name"; then
eval "$name=$(quote_str "$value")";
fi
done < "$input_file";
echo "$srcdir"
echo "$prefix"
답변3
#!/bin/sh
FILENAME="<path>"
while read LINE
do
echo "$LINE"
if echo "$LINE" | grep -E -q "^srcdir*"
then
LINE=$(echo $LINE | cut -d"#" -f1) # No Comment, strip part after #
LINE=$(echo $LINE | awk -F" // " '{print $1;}') # No Comment, strip part after //
LINE=$(echo $LINE | tr -d ' ')
srcdir=$(echo $LINE | tr -d '^srcdir=')
break
fi
done < "$FILENAME"
echo $srcdir