커맨드 라인 인수를 디자인하는 좋은 습관은 무엇입니까?


190

응용 프로그램을 개발하는 동안 궁금해지기 시작했습니다. 명령 줄 인수를 어떻게 디자인해야합니까?

프로그램의 많은이 같은 공식 사용 -argument value또는 /argument value. 내 마음에 온 해결책은 argument:value입니다. 공백이 없으면 값과 인수를 엉망으로 만들 수있는 방법이 없기 때문에 나는 그것이 좋다고 생각했습니다. 또한 왼쪽 :문자 에서 처음에 문자열을 두 개로 나누는 것이 쉽습니다 .

내 질문은 :

  1. 인기있는 -argument value공식이보다 우수 합니까 argument:value(읽기 쉽고 작성하기 쉽고 버그가 없으며 전문 개발자가 이해하기 쉽습니까)?
  2. 명령 줄 인수를 디자인 할 때 따라야하는 일반적으로 알려진 규칙이 있습니까 (작동하는 경우 제외) 괜찮습니까?

더 자세한 내용을 물어 보았습니다. 그러나 나는 그들이 대답에 영향을 미치지 않아야한다고 생각합니다. 문제는 일반적으로 좋은 습관에 관한 것입니다. 모든 종류의 응용 프로그램에서 모두 동일하다고 생각합니다.

우리는 공공 장소 (터치 토템, 테이블)에서 사용될 응용 프로그램을 연구하고 있습니다. 응용 프로그램은 Qt Quick 5 (C ++, QML, JS)를 사용하여 작성됩니다. 장치에는 Windows 8.1 / 10이 설치됩니다. 장치를 관리하기위한 프런트 엔드 인터페이스를 제공합니다. 그러나 일부 고급 관리자는 자체적으로 응용 프로그램을 구성하려고 할 수 있습니다. 비즈니스 측면에서 그다지 중요하지는 않지만 Kilian Foth의 말에 동의 할 때 응용 프로그램이 사용자에게 고통 스럽지 않게하고 싶습니다. 인터넷에서 내가 원하는 것을 찾지 못했습니다.


보다 고급 Stack Exchange 사용자에게 :이 질문이 일반적인 것이기를 바랍니다. 어쩌면 커뮤니티 위키에 적합 할 수도 있습니다 (기존 질문이 답변으로 변환 될 수 있는지 여부는 모르겠습니다). 이 질문이 운영 체제 및 프로그래밍 언어와 독립적이기를 원하므로 여기에 표시된 답변은 다른 개발자에게 유용한 교훈이 될 수 있습니다.


14
널리 사용되는 명령 줄 도구를 살펴보십시오. 예를 들어, 단일 하이픈은 종종 결합 옵션을 허용하는 데 사용됩니다. 예를 들어 당신이 쓸 수있는 ls -ltr옵션을 결합 -l, -t-r. GNU 스타일 프로그램은 일반적으로 --reverse대신에 이중 하이픈이있는 단어 기반 옵션을 허용 -r합니다. -h도움말을 표시하거나, --옵션의 끝을 -
알리고

72
흔하지 도 -argument value않습니다 -argument:value. 공통은 -a value, -avalue--argument=value입니다.
reinierpost

39
널리 사용되는 명령 줄 구문 분석 라이브러리 (보통 getopt(s))를 사용하십시오.
reinierpost

5
@ k3b 우리는 Qt와 협력하고 있습니다. 으로 케빈 클라인은 말했다 자신의 의견 우리는 이미 사용 가능한 라이브러리를 사용할 수 있습니다. 나는 그것이 다중 플랫폼이며 잘 생각한다고 가정합니다. QCommandLineParser
Filip Hazubski

11
최종 블 러브의 문제점은 인수 파싱이 플랫폼 독립적 인 문제가 아니라는 것입니다.
pydsigner

답변:


237

POSIX 시스템 (예 : Linux, MacOSX)에서는 적어도 쉘 터미널 (예 : 대부분)에서 시작될 수있는 프로그램의 경우 GNU 코딩 규칙 (공통 인수 이름도 나열 됨)을 사용하고 POSIX 유틸리티 지침을 살펴 보는 것이 좋습니다. 독점 소프트웨어의 경우에도 :

  • 항상 처리 --version하고--help (심지어도 /bin/true받아들입니다 !!). 나는 이해하지 못하는 소프트웨어의 저자를 저주한다 --help. 나는 그들을 싫어한다 ( 새로운 프로그램을 시도 prog --help 하는 첫 번째 명령 이기 때문에 )! 종종 다음 --help과 같이 축약 될 수 있습니다-h

  • --help(당신이 가장 일반적인 그 경우 목록에 ... 그들을 너무 많이하지 않는 한 모든 옵션 메시지 목록을 명시 적으로는 약간의 참조 man및 옵션 기본값 페이지 또는 일부 URL), 그리고 아마도 중요한 (및 프로그램 별 ) 환경 변수. 옵션 인수 오류에 이러한 옵션 목록을 표시하십시오.

  • 동의 -a짧은 인수 (단일 문자) 및 일부 상당을 가지고 --long-argument있으므로 -a2 --long-argument=2, --long-argument 2; 물론 당신은 (드물게 사용되는 옵션을 위해) 어떤 --only-long-argument이름을 가질 수 있습니다 . 추가 옵션 -cf이 없는 모달 인수의 경우 일반적으로 -c -f등 으로 처리 되므로 -argument:value제안이 이상 하므로 권장하지 않습니다.

  • GLIBC getopt_long 이상을 사용하십시오 (예 : argp_parse , OCaml에서는 Arg모듈입니다 ...)

  • 종종 -표준 입력 또는 출력에 사용합니다 (그렇지 않으면 운영 체제가없는 일부 운영 체제에서도 처리 /dev/stdin및 처리 /dev/stdout)

  • 대부분의 옵션 규칙을 재사용하여 유사한 프로그램의 동작을 모방합니다 . 특히 -n드라 이런 (a la make), -h도움, -v자세한 정보 등을 위해 ...

  • --옵션과 파일 또는 다른 인수 사이의 구분자로 사용

  • 프로그램 isattystdin 이 터미널 보다 테스트 하는 데 사용 하고 (이 경우 "대화식"으로 작동하는 경우) 프로그램에 GUI 인터페이스가 있고 ( getenv("DISPLAY")X11 데스크탑에서 테스트하는 경우) 비 대화식 모드를 강제 실행하는 옵션을 제공하십시오. 배치 또는 명령 행에서 사용하십시오.

  • 일부 프로그램 (예 gcc:)은 간접 인수 목록을 허용하므로 다음 @somefile.txt에서 프로그램 인수를 읽습니다 somefile.txt. 이것은 프로그램이 매우 많은 인수를 수락 할 때 유용 할 수 있습니다 (커널의 것 이상 ARG_MAX)

BTW, 당신은 심지어 당신의 프로그램과 일반적인 쉘 ( bash또는 같은 zsh)을 위해 자동 완성 기능을 추가 할 수도 있습니다

일부 오래된 유닉스 명령 (예 : dd또는 심지어 sed)은 이전 호환성을 위해 이상한 명령 인수를 갖습니다. 나는 그들의 나쁜 습관을 따르지 않는 것이 좋습니다 (당신이 더 나은 변형을 만들지 않는 한).

소프트웨어가 관련 명령 줄 프로그램의 시리즈에서 영감을 가지고 있으면 자식 수용 (당신은 분명히 개발 도구로 사용), git help그리고 git --help많은이 gitsubcommandgitsubcommand--help

드문 경우이지만 argv[0], 프로그램에서 심볼릭 링크를 사용하여 다른 동작이있는 bash것처럼 호출 될 수도 있습니다 ( 쉘 제한 ). 그러나 나는 보통 그렇게하지 않는 것이 좋습니다. 프로그램을 shebang을 사용하여 스크립트 인터프리터로 사용할 수 있다면, 즉 execve (2)에 의해 해석되는 첫 번째 라인에서 이해할 수 있습니다 . 그러한 트릭을 수행하는 경우 메시지를 포함하여 해당 트릭을 문서화하십시오 .rbash#!--help

POSIX에서 은 인자를 붙잡기 때문에 (프로그램을 실행 하기 전에 !) 쉘 이스케이프해야하는 옵션에 문자 ( *또는 $또는 같은)를 요구하지 마십시오 ~.

경우에 따라 GNU guile 또는 Lua 와 같은 인터프리터를 소프트웨어에 내장 할 수 있습니다 ( 프로그래밍 언어 전문가가 아닌 경우 자체 Turing-complete 스크립팅 언어를 발명하지 마십시오 ). 이것은 소프트웨어 디자인에 깊은 영향을 미칩니다 (따라서 초기에 생각해야합니다!). 그런 다음 스크립트 나 표현식을 해당 인터프리터에게 쉽게 전달할 수 있어야합니다. 이 흥미로운 접근 방식을 취한다면 소프트웨어와 해석 된 기본 요소를주의해서 디자인하십시오. 이상한 사용자가 큰 스크립트를 코딩하도록 할 수 있습니다.

다른 경우에는 고급 사용자가 플러그인 을 소프트웨어에 로드하도록 할 수 있습니다 ( 동적 로딩 기술 (일명 dlopen& & dlsym)). 다시 말하지만 이것은 매우 중요한 디자인 결정 (플러그인 인터페이스를 정의하고 문서화 함)이므로 프로그램 옵션을 이러한 플러그인으로 전달하는 규칙을 정의해야합니다.

소프트웨어가 복잡한 경우 일부 구성 파일 (프로그램 인수의 추가 또는 교체)을 허용하고 모든 코드를 실행하지 않고 이러한 구성 파일을 테스트 (또는 구문 분석) 할 수있는 방법이있을 것입니다. 예를 들어, Exim 또는 Postfix와 같은 메일 전송 에이전트는 상당히 복잡하며 "반 건조"로 실행할 수있는 것이 유용합니다 (예 : 실제로 이메일을 보내지 않고 특정 이메일 주소를 처리하는 방법 관찰).


(가) 알 수 있습니다 /optionWindows 또는 VMS 것입니다. 파일 계층 구조가 /디렉토리 분리 자로 사용되기 때문에 POSIX 시스템에서는 미쳤 으며 쉘은 글 로빙을 수행하기 때문입니다. 내 대답은 대부분 Linux (및 POSIX)입니다.


추신 가능한 경우, 프로그램을 무료 소프트웨어로 만드십시오. 일부 사용자 및 개발자로부터 개선이 이루어집니다 (그리고 새로운 프로그램 옵션을 추가하는 것이 종종 기존의 자유 소프트웨어에 추가하는 가장 쉬운 것 중 하나임). 또한 귀하의 질문은 의도 한 청중에 따라 크게 달라집니다 . 십대를위한 게임이나 할머니를위한 브라우저는 아마도 컴파일러, 데이터 센터 시스템 관리자를위한 네트워크 관리자 또는 마이크로 프로세서를위한 CAD 소프트웨어와 같은 종류와 양의 옵션이 필요하지 않을 것입니다 건축가 또는 교량 설계자. 프로그래밍 및 스크립팅에 익숙한 엔지니어는 아마도 할머니보다 훨씬 많은 조정 가능한 옵션을 선호하며 아마도 X11 (아마도 crontab직장에서) 없이 응용 프로그램을 실행할 수 있기를 원할 것입니다 .


18
동의하지만 git 더 좋은 예입니다. 난 추천하지 않습니다 찾고cvs2016 년에
실레 Starynkevitch

8
+ 잘못된 옵션의 경우 도움말을 표시하십시오. 예를 들어에 쓸모없는 오류 메시지가 표시되는 것은 짜증나는 일 dd -h입니다.
domen

8
GNU 프로그램 --help은 일반적으로 지원 하지만 -h성가신 것을 인식하지 못하는 경우가 많습니다 . 프로그램에 대한 옵션을 잊었을 때 일반적으로 -h를 입력하면 더 긴 옵션으로 명령을 다시 입력해야합니다 --help. 결국, 나는 무언가를 잊었 기 때문에 -h를 입력했다. 사용자에게 '-도움말'이 필요한 프로그램과 도움말 화면을 표시하기 위해 '-h'가 필요한 프로그램을 기억해야하는 이유는 무엇입니까? -h 및 --help 옵션을 모두 포함하십시오.
Brandin

30
이 답변의 첫 부분은 좋지만 당신을 따라 어딘가에 접선이 있습니다. 예를 들어, 구성 파일, 플러그인 및 dlopen, 소프트웨어 라이센스 선택 및 웹 브라우저는 더 이상 명령 행 인터페이스의 규칙과 관련이 없습니다.
Brandin

5
그리고 제발 화면 출력을 형식화하는 경우 출력 형식 대체를 추가하십시오. 스크립트에서 줄을 사용하려고 할 때 줄을 자르거나 줄 바꿈하는 명령보다 더 귀찮은 것은 없습니다.
Sobrique

68

데이터 형식 규칙이 인기가 있다는 사실 입니다 자사의 장점.

구분 기호로 = 또는 : 또는 ''를 사용하면 약간의 노력만으로도 컴퓨터로 서로 변환 할 수있는 사소한 차이가 있음을 쉽게 알 수 있습니다. 어떤 것이 노력하는 것은 인간이 기억하기위한 것입니다 "이 자주 사용하는 프로그램이 함께 일을 구분 한 참조 지금 :이나와 =? 흠 ..."

다시 말해, 신을 사랑하기 위해 설득력있는 이유없이 굳건한 관습에서 벗어나지 마십시오. 사람들은 당신의 프로그램을 "내 대학 에세이를 저장 한 것"대신 "이상하고 성가신 cmdline 구문을 가진 것"으로 기억할 것입니다.


19
거의 모든 언어에는 명령 줄 인수를 처리하는 라이브러리 함수가 있습니다. 그중 하나를 사용하십시오.
케빈 클라인

9
좋은 조언이지만 그 규칙은 무엇입니까? -1
RubberDuck

14
이 규칙을 의도적으로 위반하는 일반적으로 사용되는 UNIX 도구의 흥미로운 예가 있습니다. 구문을 dd사용 key=value합니다. 이 디자인 결정에 대한 이유는이 도구 (별명이다 D ATA D 잘못 사용할 경우 많은 피해가 발생할 수 estroyer가). 사용자가 일반적인 습관을 버릴 수있게함으로써 사용자는 자신이하는 일에 대해 더 자세히 생각하게됩니다.
Philipp

18
그게 확실한 이유 dd입니까? 커널의 ARG_MAX가 작고 쉘에 자동 완성 기능 --long-arguments이 없었고 존재하지 않았을 때 (1970 년대) 단순히 코딩 된 것으로 생각 합니다. 그 이후로 더 나은 dd호환성을 유지했습니다
Basile Starynkevitch

9
dd다른 OS (UNIX보다)-IBM OS / 360의 JCL (scripting-language)-UNIX에서 거의 변경되지 않은 상태로 포팅되기 전에 규칙이 다른 곳에서 사용되었습니다. 이전 시스템.
Baard Kopperud

29

평신도의 관점에서

로마에있을 때 로마인들이하는 것처럼하십시오.

  • CLI 앱이 Linux / Unix 용인 경우 -p value또는 --parameter value규칙을 사용하십시오 . 리눅스는 그러한 매개 변수와 플래그를 쉽게 분석 할 수있는 도구를 가지고 있습니다.

나는 보통 이런 식으로합니다 :

while [[ $# > 0 ]]
do
key="$1"
case $key in
    --dummy)
    #this is a flag do something here
    ;;
    --audit_sessiones)
    #this is a flag do something here
    ;;
    --destination_path)
    # this is a key-value parameter
    # the value is always in $2 , 
    # you must shift to skip over for the next iteration
    path=$2
    shift
    ;;
    *)
    # unknown option
    ;;
esac
shift
done
  • CLI 앱이 Windows 용인 경우 사용 /flag/flag:value규칙입니다.

  • Oracle과 같은 일부 앱은 둘 다 사용하지 않습니다. 오라클 유틸리티는을 사용 PARAMETER=VALUE합니다.

  • 내가 좋아하는 한 가지는 명령 줄에서 매개 변수를 수락하는 것 외에도 parfile을 사용하는 옵션을 제공하는 것입니다. parfile 은 긴 매개 변수 체인을 피하기 위해 키-값 쌍 파일입니다. 이를 위해 추가 --parfile mifile.par매개 변수를 제공해야합니다 . 분명히 --parfile사용되면 다른 모든 매개 변수는 파 파일 내부의 내용을 위해 삭제됩니다.

  • 추가 제안은 일부 사용자 정의 환경 변수를 사용할 수 있도록하는 것입니다. 예를 들어 환경 변수를 설정 MYAPP_WRKSPACE=/tmp하면 항상 설정할 필요가 없습니다 --wrkspace /tmp.

  • 리눅스에서는 매개 변수 자동 완성 기능 을 추가하는 것을 잊지 마십시오 . 즉, 사용자는 스위치의 절반을 입력하고 적중 TAB한 다음 쉘이이를 완료 할 수 있습니다.

1
글쎄, 몇몇 GNU 유틸리티 (예 gcc:) @mifile.par는 당신의 --parfile mifile.par제안 처럼 처리 합니다 .
Basile Starynkevitch

7
매개 변수 파일이있는 경우 다른 모든 옵션을 무시 하시겠습니까? 기껏해야 반 직관적입니다.
Jonathan Leffler

8
매개 변수 파일에 대해서는 Jonathan과 동의합니다. 매개 변수 파일이 존재하면 명령 줄에 주어진 인수가 파 파일의 인수 위에 적용되어 기본값으로 사용될 것으로 기대합니다. 어떤 이유로 파 파일을 사용하여 추가 명령 행 인수를 사용할 수없는 경우 추가 인수가 있으면 오류가 발생합니다.
Eldritch Cheese

@EldritchCheese 필자가 작성한 CLI 앱에서 파 파일이 주어지면 추가 매개 변수가 오류를 생성합니다.
Tulains Córdova

1
가능한 쉘을 사용하는 경우, 이런 종류의 "config file parameter"옵션은 필요하지 않습니다. 예를 들어 fooCmd -opt1 -opt2 $(cat more_options.opts). 따라서 "config file parameter"옵션이 제공되는 경우 기본적으로 동일한 방식으로 작동해야합니다.
Brandin

19

아직 나오지 않은 것 :

명령 행 인수에서 위쪽으로 소프트웨어를 설계하십시오 . 의미:

기능을 설계하기 전에 사용자 인터페이스를 설계하십시오.

이를 통해 에지 케이스와 일반적인 케이스를 조기에 드릴 다운 할 수 있습니다. 물론 외부와 내부를 추상화하지만 모든 코드를 작성한 다음 CLI를 슬래 밍하는 것보다 훨씬 나은 결과를 얻을 수 있습니다.

또한 docopt ( http://docopt.org/ )를 확인 하십시오 .

docopt는 많은 언어에서, 특히 argparse와 같이 사용자가 제한하는 사용자 파서 파서가 여전히 "OK"로 간주되는 파이썬의 경우 큰 도움이됩니다. 구문 분석기와 하위 구문 분석기 및 조건부 dicts 대신 구문 도움말을 정의 하고 나머지는 수행합니다.


나는이 답변을 좋아하고 고마워합니다. 현재 argparse프로그래머, 사용자 인터페이스 또는 사용자 친화적이 아닌 것에 좌절하고 있습니다.
고양이

docopt를 시도했지만 마음에 들지 않습니다. 하위 명령이있을 때 옵션이 약간 적지 만 클릭 하면 코드 가 훨씬 깨끗해집니다.
jpmc26

2
이것은 광고와 너무 비슷합니다. 관련이 있으면 리소스를 한 번만 언급하십시오. 그러나 현재로서는 50 %의 답변이 외부 리소스를 홍보하는 것처럼 들립니다.
Brandin

나는 그것을 '사용 모델을 먼저 디자인하라'라고 말하고 싶습니다. 사용자 경험과 기능을 분리하는 것은 많은 경우 인공적인 구별이 될 수 있습니다 (도구 제한이 인터페이스에 영향을 미침).
copper.hat

1
Docopt의 경우 +1 모든 CLI 딜레마를 완전히 고쳤습니다. 때때로 진정한 열정으로 광고를하기는 어렵지만 여기에 있습니다. 저는 몇 년 동안 Docopt 애호가였으며 어떤 방식으로도 제휴하지 않았습니다.)
frnhr

3

몇 가지 귀중한 의견이 이미 제공되었지만 (@Florian, Basile), 추가하겠습니다 ... OP는 말합니다.

장치를 관리하기위한 프런트 엔드 인터페이스를 제공합니다. 그러나 일부 고급 관리자는 자체적으로 응용 프로그램을 구성하려고 할 수 있습니다

그러나 또한 언급 :

이 질문이 플랫폼이나 언어에 국한되지 않기를 바랍니다.

대상 대상 고급 관리자를 고려해야합니다 . Win / Unix / Mac에서 일반적으로 어떤 플랫폼에서 작동합니까? 그리고 어떤 플랫폼에서 앱을 실행합니까? 해당 플랫폼에 대해 이미 설정된 CLI 규칙을 따르십시오. "고급"관리자가 GUI 기반 도구를 원하거나 필요로합니까?

내부 및 다른 관리 도구와 인터페이스의 일관성을 유지하려고합니다. 나는 중지하고 생각하고 싶지 않은 것은이다 cmd -p <arg>또는 cmd -p:<arg>cmd /p <arg>. 공백이 있으면 따옴표가 필요합니까? I 수 cmd -p <val1> <val2>또는 cmd -p <val1> -p <val2>여러 대상? 주문이 구체적입니까? 과부하? cmd -p2 <arg> -p1 <arg>작동 합니까 ? 않습니다 ls -l -r -t dir1 dir2== ls -trl dir1 dir2?

필자는 유닉스 관리 도구 를 위해 언급 된 다른 참고 자료와 함께 Heiner 's Shelldorado 가 제공 한 지침을 항상 염두에 두었 습니다.

CLI를 설계하는 것만 큼 중요한 것은 응용 프로그램이 GUI와 같은 명령 줄 인수와 함께 작동하도록 설계하는 것입니다. 즉, GUI에 비즈니스 로직이 없거나 GUI와 CLI에서 호출 된 공통 명령을 사용합니다.

대부분의 UNIX 기반 관리 도구는 실제로 먼저 명령 행 도구로 설계되며 제공된 GUI는 단순히 명령 행 옵션을 "채우기"용이하게합니다. 이 접근 방식을 사용하면 자동화, 응답 파일 사용 및 핸드 오프 관리가 가능합니다 (나에게 도움이되지 않음).

이 툴을 사용하는 기존 툴셋은 Tcl / Tk 입니다. 공구 교환을 제안하지 않습니다. GUI 기반 관리 앱을 명령 줄 도구로 먼저 앱에 작성하는 것에서 디자인 접근 방식을 고려하십시오. 그런 다음 편의상 GUI를 맨 위에 놓습니다. 어떤 시점에서 여러 구성을 수행하고 일반적으로 동일한 옵션을 반복해서 다시 입력 해야하는 경우 GUI가 고통스럽고 오류가 발생하기 쉽다는 것을 알게 될 것입니다. 자동 접근 방법을 찾으십시오.

어쨌든 관리자는 올바른 상자에 올바른 값을 입력해야 할 것이므로 기억하십시오.


그래요! 한 가지 질문도 있습니다 : ./this-script --hosts <hosts.txt를 실행할 수 있습니까?
Florian Heigl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.