ksh에서 "[["와 "-e xxx"사이에 공백이 필요한 이유는 무엇입니까?


9

예를 들어 다음 명령이 작동하지 않습니다.

if [[-e xyz]]; then echo File exists;fi

ksh는 다음 오류를 제공합니다

[[-e: command not found

"[[-"가 모호하기 때문입니까?


2
[[A는 키워드 - 아마 쉘의 구문 분석 트리 키워드는 공백으로 묘사되어야 함을 요구한다
steeldriver

그것을 보는 또 다른 방법은 아마도 함수 [[-, 쉘이 "[[e on e"함수 대신 "[e"에서 e 플래그를 분석하는 방법을 어떻게 알 수 있을까)를 작성할 수 있다는 것입니다.)
pbhj 2016 년

답변:


15

같은 설명서가 나타나기 때문에 가장 간단한 설명은 것 [[ expression ]]사이의 공간이 있어야한다 그래서 [[expression닫는 ]]. 물론 우리는 더 깊이 살펴볼 수 있습니다. 쉘은 다소 복잡한 문법을 ​​가지고 있으며 "단어 분리"라는 개념에 크게 의존합니다. 특히 ksh (1) 수동 상태는 다음과 같습니다.

쉘은 입력을 단어로 분리하여 입력 구문 분석을 시작합니다. 일련의 문자 인 단어는 따옴표없는 공백 문자 (공백, 탭 및 줄 바꿈) 또는 메타 문자 (<,>, |,;, &, (및))로 구분됩니다. 구분 단어 외에도 공백과 탭은 무시되고 개행은 일반적으로 명령을 구분합니다.

따라서 매뉴얼에 명시된 바와 같이 일련의 문자 [[-e는 쉘 단어로 간주됩니다. ksh내장 및 특수 연산자 ( for또는 같은 while) 목록에서 이러한 명령을 찾은 다음 외부 명령을 찾고 voilà를 찾을 수 없으므로 명령을 찾을 수 없다는 오류 메시지가 표시됩니다.

이 경우 [[특수 메타 문자도 아닙니다. 만약 그렇다면, 그 -e부분은 그 자체에 [[-e대한 주장이 아니라 쉘 단어로 간주 될 [[것입니다. 그러나 [[복합 명령으로 설명되며 설명서에는 다음과 같이 나와 있습니다.

복합 명령은 다음 예약어를 사용하여 작성됩니다.이 단어는 따옴표가없고 명령의 첫 번째 단어로 사용되는 경우에만 인식됩니다 (즉, 매개 변수 지정 또는 재 지정이 앞에 올 수 없음).

따라서 [[복합 명령으로 인식 되려면 명령 또는 명령 목록의 첫 번째 단어 여야합니다. "단어"의 이전 정의에 따라 공백, 탭 또는 줄 바꿈으로 구분해야 함을 의미합니다. 단어 / 인수.


당신은에 요청했습니다 의견 : "할 수없는 이유는 파서 정지, 발견 즉시로"[[ "패턴 및 취급이 조건부 명령의 시작으로?" 짧은 대답은 아마도 1) [구문이 원래 외부 명령 이기 때문에 구문의 영향이고 POSIX 표준 준수의 경우 오늘날에도 외부 명령으로 존재하기 때문이며 2) 쉘 파서가 그렇게 작성 되었기 때문일 것입니다. 쉘 파서는 공백이 아닌 다른 특수 문자를 인식 echo $((2+2))하고 (echo foobar)완벽하게 작동합니다. 어쩌면 미래에 ksh개발이 재개되거나 포크 또는 클론이있는 것처럼 보일 때 (예 : mksh또는 pdksh) 누군가가 공백없는 구문을 구현할 것입니다 [[-e.

또한보십시오:


3
나는 ksh 매뉴얼 인용이 실제로 그 자리에 있다고 생각합니다. 그것은 다른 프로그래밍 언어와 유사 :에서 C, char키워드입니다하지만 당신은 여전히 쓸 수 없습니다 charsomeletter = 'A';및보고 후 정지 파서를 기대합니다 char.
피터-복원 모니카

"char"예제와 질문에서 "[["기호의 주요 차이점은 일반적으로 영숫자 식별자는 다른 문자와 구분하기 위해 공백 구분 기호가 필요하다는 것입니다. 반면 토큰과 같은 특수 기호는 공백 구분 기호가 필요하지 않습니다.
AcBap

바로 그거죠. C와의 비교가 도움이되는지 확실하지 않습니다. C에서는 말할 수 i--<=++j있으며 컴파일러는로 구문 분석하는 데 아무런 문제가 없습니다 i -- <= ++ j.
Scott

@ Scott C 비교가 도움이된다고 생각합니다 (C 식별자는 영숫자 만 허용한다는 것은 부차적입니다 _). KSH을 갖는다 (int로서 연산자(echo hello)로 파싱한다 ( echo hello ). 그것은했다 if, {, [[, 등의 키워드ifx, {x그리고 [[x각각의 토큰입니다 - 방법과 같은 charsomeletter하나의 C 토큰입니다. 대조적으로, 인용되지 않은 (xksh는 i--C에서 두 개의 토큰이 어떻게되는지와 같이 두 개의 토큰입니다. 개념적 으로 연산자라는 의미 는 Bourne 스타일 쉘 (ksh와 같은)과 C가 다릅니다. 그러나 Peter A. Schneider는 실제 어휘 유사성.
엘리아 케이건

2

주목해야 할 [것은 명령이며 [[bash 및 ksh 의 쉘 키워드 는를 기반으로 한다는 것 입니다 [.

[[와 유사한 방식으로 사용됩니다 [. 때로는 당신도 대체 할 수 [ ][[ ]]행동의 변화없이. 을 사용 [하면 명령과 마찬가지로 명령과 인수 사이에 공백이 필요합니다. 동일하게 적용됩니다 [[.

우리는 단지 가지고 있었다 /usr/bin/[. 이제 대부분의 셸은 [효율성을 위해 내장되었지만 구문은 동일합니다. 제공 쉘에서 [[A와, 그 기능을 더욱 다양한 대안을 [.

[bash에 대한 설명은 다음과 같습니다 .

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

따라서 ( 마지막 으로 논쟁 을 기대하는 것을 제외하고 [)와 같습니다 . 그것에 대해 더 자세히 알려줄 것입니다. 이것을와 비교할 수 있습니다 .test]help testhelp [[

외부 명령 [( man \[)에 대한 매뉴얼 페이지도 있습니다 .

의 경우

if [[-e
  • 거기에는 명령 도 [없습니다 [[. 전체 단어 [[-e입니다.
  • if [[-e그것을 참 / 거짓에 대한 테스트합니다. 그래서 명령 않는 [[-e존재를?

"[[-"가 모호하기 때문입니까?

예. 아님 [[-e쉘이 이해하는 것은 아무것도 없으므로 쉘이 자체 명령이라고 가정합니다. ;-)


"% help [["는 "[["는 조건부 명령이라고 말합니다. 파서가 "[["패턴을 발견하자마자 멈추지 않고이를 조건부 명령의 시작으로 취급 할 수없는 이유는 무엇입니까?
AcBap

@Myloti [[-e는 잠재적으로 유효한 (이상해 보이는 경우) 명령 이름입니다.
Gordon Davisson

2

공간은 델리 미네 이터 이며 필수입니다. 당신이 볼 수 있듯이 shellcheck:

$ shellcheck gmail-browse-msgs-algorithm.sh

In gmail-browse-msgs-algorithm.sh line 847:
        [[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
          ^-- SC1035: You need a space after the [[ and before the ]].

(ksh와 bash는 모두 [[공백없이 작동하며 작동하지 않습니다. Shellcheck는 해당 버기 라인을 포함하는 유사한 ksh 및 bash 스크립트로 출력을 정확하게 제공합니다.)

델리 미네 이터가 필요한 이유는 토큰 및 사전과 관련이 있습니다.


OP는 질문에 ksh쉘에 대해 물었습니다 . Bash는 [[운영자 ksh에게이 질문에서 운영자를 빌려 주지만 그들의 행동은 동일하지만 행동과 내부 ksh와는 약간의 차이가 있기 때문에 가정에주의를 기울일 것 bash입니다. 쉘 검사가 bash 스크립트에서 작동하기 때문에 ksh 스크립트에 적합한 도구 일 필요는 없습니다. 다른 조개에 접근하면서 그냥 뭔가 마음에 유지
세르지 Kolodyazhnyy에게

@SergiyKolodyazhnyy 나는 [[내장 규칙 을 강조하기 위해 shellcheck를 사용하여 기회 주의적이었습니다 . 나는 그것이 오류를 발견 할 수 ksh있는 쉘이라는 것을 결코 추론하지 않았다 shellcheck. 나는 다른 사람들 이 서로 다른 두 가지 통역사를 이해 ksh하고 이해하기를 바란다 bash. 언급 해 주셔서 감사합니다. 또한 외부 명령 인 [[내장 bash 도 주목할 가치가 [있습니다.
WinEunuuchs2Unix 2016 년

실제로 [는 bash에 내장되어 있습니다 :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html 그러나 당신은 멀지 않습니다- [또는 test외부 명령이 필요합니다. 원래 Bourne 쉘 시절에는 [실제로는 외부 명령 이었지만 /usr/bin/[POSIX는 외부 명령 이어야 하기 때문에 오늘날에도 여전히 존재합니다. pubs.opengroup.org/onlinepubs/009695399/utilities/test.html POSIX에 필요한 것은 거의 없습니다 내장 된 pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html 내장 [은 효율성을위한 것입니다
Sergiy Kolodyazhnyy 2018 년

2
Shellcheck는 알고있다 ksh; hashbang 또는을 사용하십시오 -s ksh. BTW, KSH 및 배쉬있다 [["내장"그러나 A의 키워드 는 달리, [A는, 쉘 내장 . (ksh : whence -v [ [[; bash type [ [[:) 내장 명령과 외부 명령은 구문 적으로 비슷합니다. 한 가지 [[다른 점은 인수에서 일부 확장 [[[억제 한다는 것 입니다. 인수로는 내장 기능이 아니기 때문에 내장 기능으로 {는 불가능했습니다. 이 이유가 될 수있다 {x(또는 [[x) 홀수 하나의 토큰 Feel로 서비스를 제공합니다. 내장과 키워드는 어휘 적이지만 구문 적으로 비슷 하지 않다고 말하는 것이 옳습니다 . @SergiyKolodyazhnyy
엘리아 케이건

1
사실, 난 POSIX이 상황에 대해 어떻게 생각하는지에 대한 정확한 답을 얻을 U & L에 질문을 게시 한 @EliahKagan unix.stackexchange.com/questions/526574/... 쉘 언어 것은 복잡한만큼 그렇게 잘하면 사람이 형식적인 관점에서 설명 할 수있다
Sergiy Kolodyazhnyy 2018 년

1

[[외부 명령이 될 수 있습니다! 즉, 프로그램 일 수 있으며 쉘에서 직접 지원하는 일부 구문은 아닙니다. 공간이없는 구문을 지원할 수는 ksh있지만 외부가있는 시스템에서는 실패 [[하므로 호환성을 위해 필요한 공간을 유지하는 것이 좋습니다.

[[예를 들어 BusyBox는 외부 명령으로 제공 하고 있습니다.


0

[[-e쉘 확장에 참여할 수 있기 때문에

echo [[-e]*

편지와 함께 시작하는 모든 파일을 나열하기 위해 [하고 e있는 경우 포괄적으로)를, 그것은 완전한 엉망이 될 것입니다 []특수 문자는 일반 공백 지배 단어 분할에 참여하지 않았다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.