たとえば、
srcdir = ../libc # Src directory
prefix = /usr/local // Installation path
最初の行はmakefileから取得され、2行目はconfig.make
.
シェルスクリプトの$srcdir
変数にアクセスする必要があります$prefix
。
` = `
私が見つけた1つの解決策は、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