일전에 기술팀이 아닌 팀을 위한 스크립트를 작성하고 있었는데, 난해한 명령줄 플래그를 문장처럼 읽는 명령으로 대체해야겠다고 생각했습니다.
나는 명령줄을 생각해 냈습니다.
<script.sh> run tests for <module> ... in <language> ...
키워드 "for"는 모듈 목록을 소개하고 "in"은 언어 목록을 소개합니다. (덧붙여 "in" 자체가 장래에는 언어 코드가 될 수도 있습니다.)
내가 구문 분석하는 방법은 상위 수준 구조를 로 정의하는 것입니다. +="run test"인 경우 "for" 및 "in" 키워드를 찾기 위해 특정 구문 분석을 시작합니다.
다음으로 구문을 다음과 같이 변경하고 싶습니다.
<script.sh> run <module> ... tests in <language> ...
제 생각엔 이게 더 읽기 좋은 것 같아요.
손으로 만든 Bash 매개변수 구문 분석을 통해 이를 수행할 수 있지만 제 생각에는 이것이 너무 복잡합니다. 또 다른 옵션은 Lex/Yacc입니다. 스크립트는 임시 Lex+Yacc 스크립트를 작성하고 이를 사용하여 명령줄을 구문 분석할 수 있습니다. 이것도 너무 나간 것 같습니다.
위의 명령줄을 변수로 구문 분석하는 데 사용할 수 있는 간단한 컨텍스트 자유 문법을 정의하는 훌륭하고 간단한 방법이 있습니까? 본격적인 해결책이 아닌 출발점이라는 소식을 들으니 기쁘다.
답변1
꽤 투박하지만 올바른 방향을 알려주어야 합니다.
구문 분석은 주어진 프로그램을 해석(또는 컴파일 및 실행)하는 과정의 한 단계일 뿐입니다. 쉘 매개변수를 어휘 표시로 사용하는 것이 편리합니다. 해석에 관한 한, 구문 분석 및 해석기 논리를 작업 구현과 별도로 유지하는 것이 좋습니다. 작업을 수행하기 위해 명시적으로 명명된 함수를 사용하는 것입니다. 무작동 게이트를 사용하여 작성하는 것도 가능하므로 추가 작업을 수행하지 않고도 추적하고 디버그할 수 있습니다. 처형의 흔적을 보여줄 bash -x
사람은 바로 당신의 친구입니다 .bash -x ./script.bash
이와 같은 구문 분석 논리에서 명명된 함수를 호출하는 것이 좋습니다. 작성하거나 수정하는 것은 까다로우며, 실행된 함수 대신 호출된 함수 에코 이름을 바꿀 수 있으면 더 쉽습니다.
#!/usr/bin/env bash
: ${DEBUG:=}; shopt -s extglob; [[ $DEBUG ]] && shopt -p extglob
acceptArg () {
local spec="$1" cb="$2" arg="$3" status=([args]=0 [matched]=0); shift 3;
# https://unix.stackexchange.com/a/234415/61350 # how-can-i-use-a-variable-as-a-case-condition
matcher="@($spec)"
case "$arg" in
$matcher) status[matched]=1; $cb ;;
*) [[ $DEBUG ]] && echo "spec: '$spec' failed to match arg: '$arg'";;
esac
[[ $DEBUG ]] && declare -p status
return $((status[matched] == 1))
}
count=0
incr(){ echo $((++count)); }
handleFirst(){ incr; }
handleSecond(){ incr; }
acceptArg "f|first" handleFirst "$1";
acceptArg "s|second|*2" handleSecond "$2";
[[ $? == 1 ]] && echo done || echo failed
나도 같은 것에 관심이 있고 몇 달, 몇 년 동안 뭔가를 쓸 생각을 해왔다. 문제 설명을 구체적으로 작성해 주셔서 감사합니다. 업데이트 작업 중이에요https://gist.github.com/mcint/8a589500c44d4dc08dcb09b80882c2fd