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.