쉘 스크립트에서 makefile을 사용하여 배포

쉘 스크립트에서 makefile을 사용하여 배포

예를 들어:

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

관련 정보