배치 스크립트의 문법을 조사하기위한 실험을 수행했습니다. 또한 배치 모드와 명령 행 모드의 차이점을 조사했습니다.
배치 라인 파서 :
다음은 배치 파일 행 구문 분석기의 단계에 대한 간략한 개요입니다.
단계 0) 판독 라인 :
1 단계) 확장 비율 :
2 단계) 특수 문자 처리, 토큰 화 및 캐시 된 명령 블록 작성 : 따옴표, 특수 문자, 토큰 구분 기호 및 캐럿 이스케이프와 같은 항목의 영향을받는 복잡한 프로세스입니다.
단계 3) 구문 분석 된 명령을 에코합니다 . 명령 블록이로 시작하지 않고 @
ECHO가 이전 단계의 시작에서 ON 인 경우에만 가능합니다 .
4 단계) %X
변수 확장의 경우 : FOR 명령이 활성화되고 DO 이후의 명령이 처리되는 경우에만 해당됩니다.
5 단계) 지연 확장 : 지연 확장이 활성화 된 경우에만
5.3 단계) 파이프 가공 : 양쪽에 명령이있는 경우에만
단계 5.5) 리디렉션 실행 :
6 단계) 통화 처리 / 카페 배가 : 명령 토큰이 CALL 인 경우에만
단계 7) 실행 : 명령이 실행됩니다
각 단계에 대한 세부 정보는 다음과 같습니다.
아래 설명 된 단계는 배치 파서 작동 방식의 모델 일뿐입니다. 실제 cmd.exe 내부에는 이러한 단계가 반영되지 않을 수 있습니다. 그러나이 모델은 배치 스크립트의 동작을 예측하는 데 효과적입니다.
Phase 0) Read Line : first를 통해 입력 라인을 읽습니다 <LF>
.
- 명령으로 구문 분석 할 행을 읽을 때
<Ctrl-Z>
(0x1A)는 <LF>
(LineFeed 0x0A) 로 읽습니다.
- A에 대한 검색하는 동안 GOTO 나 CALL이 라인을 읽을 때 : 라벨,
<Ctrl-Z>
그 자체로 처리됩니다 -이되어 하지 로 변환<LF>
1 단계) 확장 비율 :
- 더블
%%
은 싱글로 대체됩니다%
- 인수의 확장 (
%*
, %1
, %2
, 등)
%var%
var의 존재하지 않는 경우의 확장으로 대체하십시오
- 처음
<LF>
에는 %var%
확장 되지 않은 줄이 잘립니다.
- 전체 설명을 보려면 dbenham Same thread : Percent Phase 에서 전반부를 읽으십시오 .
2 단계) 특수 문자 처리, 토큰 화 및 캐시 된 명령 블록 작성 : 따옴표, 특수 문자, 토큰 구분 기호 및 캐럿 이스케이프와 같은 항목의 영향을받는 복잡한 프로세스입니다. 다음은이 과정의 근사치입니다.
이 단계에서 중요한 개념이 있습니다.
- 토큰은 단순히 단위로 취급되는 문자열입니다.
- 토큰은 토큰 구분 기호로 구분됩니다. 표준 토큰 구분 기호가
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
와<0xFF>
연속 토큰 구분 기호가 하나로 취급됩니다. 토큰 구분 기호 사이에 빈 토큰이 없습니다.
- 따옴표로 묶인 문자열 내에 토큰 구분 기호가 없습니다. 인용 된 전체 문자열은 항상 단일 토큰의 일부로 취급됩니다. 단일 토큰은 따옴표로 묶인 문자열과 따옴표가없는 문자의 조합으로 구성 될 수 있습니다.
다음 단계는 상황에 따라이 단계에서 특별한 의미를 가질 수 있습니다. <CR>
^
(
@
&
|
<
>
<LF>
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
<0xFF>
각 문자를 왼쪽에서 오른쪽으로보십시오.
- 그런
<CR>
다음 존재하지 않는 것처럼 제거하십시오 (이상한 리디렉션 동작 제외 )
- 캐럿 (
^
)이면 다음 문자가 이스케이프되고 탈출 캐럿이 제거됩니다. 이스케이프 된 문자는 모든 특수 의미를 잃습니다 (제외 <LF>
).
- 따옴표 (
"
)이면 따옴표 플래그를 토글하십시오. 인용 플래그 만, 활성화 된 경우 "
및 <LF>
특별하다. 다른 모든 따옴표는 다음 따옴표가 따옴표 플래그를 끌 때까지 특별한 의미를 잃습니다. 닫는 따옴표를 이스케이프 할 수 없습니다. 인용 된 모든 문자는 항상 동일한 토큰 내에 있습니다.
<LF>
항상 따옴표 플래그를 끕니다. 다른 동작은 상황에 따라 다르지만 따옴표는의 동작을 변경하지 않습니다 <LF>
.
- 탈출
<LF>
<LF>
벗겨졌다
- 다음 문자는 이스케이프됩니다. 행 버퍼의 끝에서 다음 행을 읽고 1 단계와 1.5 단계에서 처리 한 후 다음 문자를 이스케이프하기 전에 현재 행에 추가합니다. 다음 문자가
<LF>
이면 리터럴로 취급되므로이 프로세스는 재귀 적이 지 않습니다.
<LF>
괄호 안에 있지 않은
탈출
<LF>
가 제거되고 현재 행의 구문 분석이 종료됩니다.
- 라인 버퍼에 남아있는 문자는 단순히 무시됩니다.
<LF>
FOR IN 괄호 안에 블록에서
이스케이프 처리되지 않음
<LF>
로 변환 <space>
- 라인 버퍼의 끝에서 다음 라인을 읽고 현재 라인에 추가합니다.
<LF>
괄호로 묶은 명령 블록 내에서
이스케이프 처리되지 않음
<LF>
로 변환되고 <LF><space>
, 상기는 <space>
커맨드 블록의 다음 라인의 부분으로서 취급된다.
- 행 버퍼의 끝에서 다음 행을 읽고 공백에 추가합니다.
- 특수 문자
&
|
<
또는 중 하나 인 경우 >
파이프, 명령 연결 및 리디렉션을 처리하기 위해이 지점에서 줄을 분할하십시오.
- 파이프 (
|
) 의 경우 각면은 5.3 단계에서 특수 처리되는 별도의 명령 (또는 명령 블록)입니다.
- 의 경우에
&
, &&
또는 ||
명령 연결의 연결의 각 측면은 별도의 명령으로 취급된다.
- 의 경우에
<
, <<
, >
, 또는 >>
리디렉션 리디렉션 절 일시적으로 제거되고, 분석되고, 그 후 현재의 명령의 끝 부분에 추가. 리디렉션 절은 선택적 파일 핸들 숫자, 리디렉션 연산자 및 리디렉션 대상 토큰으로 구성됩니다.
- 리디렉션 연산자 앞에 오는 토큰이 이스케이프 처리되지 않은 단일 숫자 인 경우이 숫자는 리디렉션 할 파일 핸들을 지정합니다. 핸들 토큰을 찾을 수 없으면 출력 리디렉션의 기본값은 1 (stdout)이고 입력 리디렉션의 기본값은 0 (stdin)입니다.
- 이 명령에 대한 첫 번째 토큰 (리디렉션을 끝으로 이동하기 전에)이로 시작
@
하면 @
특별한 의미를 갖습니다. ( @
다른 상황에서는 특별하지 않습니다)
- 스페셜
@
이 제거됩니다.
- ECHO가 ON이면이 명령은이 행의 다음에 연결된 명령과 함께 3 단계 에코에서 제외됩니다.
@
가 여는 앞에 있으면 (
괄호 안에있는 전체 블록이 3 단계 에코에서 제외됩니다.
- 프로세스 괄호 (여러 줄에 걸쳐 복합 문장 제공) :
- 파서가 명령 토큰을
(
찾지 않으면 특별하지 않습니다.
- 파서가 명령 토큰을 찾고를 찾으면
(
새로운 복합 명령문을 시작하고 괄호 카운터를 증가시킵니다.
- 괄호 카운터가 0보다
)
크면 복합 명령문 을 종료하고 괄호 카운터를 줄입니다.
- 행 끝에 도달하고 괄호 카운터가> 0이면 다음 행이 복합 명령문에 추가됩니다 (0 단계부터 다시 시작).
- 괄호 카운터가 0이고 구문 분석기가 명령을 찾고있는 경우 즉시 토큰 구분 기호, 특수 문자, 줄 바꾸기 또는 파일 끝이 뒤에 오는 한 명령문
)
과 유사한 기능 을 수행 REM
합니다.
- 모든 특수 문자는 제외하고 의미를 잃습니다
^
(행 연결 가능)
- 논리 행의 끝에 도달하면 전체 "명령"이 삭제됩니다.
- 각 명령은 일련의 토큰으로 구문 분석됩니다. 첫 번째 토큰은 항상 명령 토큰으로 취급됩니다 (특별 항목
@
이 제거되고 리디렉션이 끝으로 이동 한 후).
- 명령 토큰 이전의 선행 토큰 구분 기호가 제거됩니다.
- 명령 토큰을 구문 분석 할 때
(
표준 토큰 구분 기호 외에도 명령 토큰 구분 기호로 작동
- 후속 토큰의 처리는 명령에 따라 다릅니다.
- 대부분의 명령은 단순히 명령 토큰 뒤에있는 모든 인수를 단일 인수 토큰으로 연결합니다. 모든 인수 토큰 분리 문자가 유지됩니다. 인수 옵션은 일반적으로 7 단계까지 구문 분석되지 않습니다.
- 세 가지 명령은 특별한 처리를합니다-IF, FOR 및 REM
- IF는 독립적으로 처리되는 2 ~ 3 개의 개별 부품으로 나뉩니다. IF 구성의 구문 오류는 치명적인 구문 오류를 초래합니다.
- 비교 연산은 7 단계로 진행되는 실제 명령입니다.
- 모든 IF 옵션은 2 단계에서 완전히 구문 분석됩니다.
- 연속적인 토큰 구분 기호는 단일 공간으로 축소됩니다.
- 비교 연산자에 따라 식별되는 하나 또는 두 개의 값 토큰이 있습니다.
- True 명령 블록은 조건 이후의 명령 집합이며 다른 명령 블록과 마찬가지로 구문 분석됩니다. ELSE를 사용하려면 True 블록을 괄호로 묶어야합니다.
- 선택적 False 명령 블록은 ELSE 이후의 명령 집합입니다. 이 명령 블록은 정상적으로 구문 분석됩니다.
- True 및 False 명령 블록은 후속 단계로 자동으로 흐르지 않습니다. 후속 처리는 7 단계에서 제어합니다.
- FOR는 DO 다음에 2 개로 분할됩니다. FOR 구문에서 구문 오류가 발생하면 심각한 구문 오류가 발생합니다.
- DO를 통한 부분은 7 단계까지 진행되는 실제 FOR 반복 명령입니다.
- 모든 FOR 옵션은 2 단계에서 완전히 구문 분석됩니다.
- IN 괄호로 묶은 절은
<LF>
로 취급 됩니다 <space>
. IN 절이 구문 분석 된 후 모든 토큰이 함께 연결되어 단일 토큰을 형성합니다.
- 이스케이프 처리되지 않은 / 따옴표없는 토큰 구분 기호는 DO를 통해 FOR 명령 전체에서 단일 공간으로 축소됩니다.
- DO 다음 부분은 정상적으로 구문 분석되는 명령 블록입니다. DO 명령 블록의 후속 처리는 7 단계의 반복에 의해 제어됩니다.
- 2 단계에서 감지 된 REM은 다른 모든 명령과 크게 다르게 처리됩니다.
- 하나의 인수 토큰 만 구문 분석됩니다. 구문 분석기는 첫 번째 인수 토큰 뒤의 문자를 무시합니다.
- REM 명령은 3 단계 출력에 나타날 수 있지만 명령이 실행되지 않고 원래 인수 텍스트가 에코됩니다. 이스케이프 캐럿은 제거되지 않습니다.
^
줄을 끝내는 이스케이프 처리되지 않은 것으로 끝나는 인수 토큰이 하나만 있으면 인수 토큰이 제거되고 후속 행이 구문 분석되어 REM에 추가됩니다. 토큰이 두 개 이상이거나 마지막 문자가 아닐 때까지 반복됩니다 ^
.
- 명령 토큰이로 시작
:
하고 이것이 2 단계의 첫 번째 라운드 인 경우 (6 단계의 CALL로 인해 다시 시작되지 않음)
- 토큰은 일반적으로 미 실행 레이블 로 취급됩니다 .
- 라인의 나머지는하지만, 구문 분석
)
, <
, >
, &
그리고 |
더 이상 특별한 의미가 없습니다. 줄의 나머지 부분은 레이블 "command"의 일부로 간주됩니다.
- 는
^
계속해서 특별합니다. 즉, 줄 연속을 사용하여 후속 줄을 레이블에 추가 할 수 있습니다.
- 미 실행 된 라벨 이 바로 다음 명령 또는하지 않는 괄호 내의 블록 치명적인 구문 오류가 발생할 것이다 라벨 실행될 다음 행.
(
더 이상 실행되지 않은 레이블 다음에 오는 첫 번째 명령에 특별한 의미가 없습니다 .
- 레이블 구문 분석이 완료되면 명령이 중단됩니다. 레이블에 대해서는 후속 단계가 수행되지 않습니다
- 2 단계에서 찾은 레이블 이 7 단계를 통해 구문 분석을 계속 하는 실행 된 레이블 로 취급 될 수있는 3 가지 예외가 있습니다 .
- 선행 라벨이 토큰 것을 재 지정이이며,이
|
파이프 나 &
, &&
또는 ||
라인에 명령 연결은.
- 레이블 토큰 앞에 리디렉션이 있으며 명령은 괄호 안에 있습니다.
- 레이블 토큰은 괄호 안에있는 행의 첫 번째 명령이며 위의 행 은 실행되지 않은 레이블로 끝났습니다 .
- 2 단계에서 실행 된 레이블 이 발견
되면 다음이 발생합니다.
- 레이블, 인수 및 리디렉션은 모두 3 단계의 모든 에코 출력에서 제외됩니다.
- 라인에서 연결된 모든 후속 명령이 완전히 구문 분석되고 실행됩니다.
- 에 대한 자세한 내용은 실행 된 레이블 대 실행되지 않은 레이블 을 참조 https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405을
단계 3) 구문 분석 된 명령을 에코합니다 . 명령 블록이로 시작하지 않고 @
ECHO가 이전 단계의 시작에서 ON 인 경우에만 가능합니다 .
4 단계) FOR %X
변수 확장 : FOR 명령이 활성화되고 DO 이후의 명령이 처리되는 경우에만 해당됩니다.
- 이 시점에서 일괄 처리 단계 1은 이미 같은 변수에 대한 변환 것이다
%%X
로 %X
. 명령 행은 단계 1에 대해 다른 백분율 확장 규칙을 갖습니다. 이것이 명령 행은 사용 %X
하지만 배치 파일 %%X
은 FOR 변수에 사용 하는 이유입니다 .
- FOR 변수 이름은 대소 문자를 구분하지만
~modifiers
대소 문자를 구분하지 않습니다.
~modifiers
변수 이름보다 우선합니다. 다음 문자 ~
가 수정 자 및 유효한 FOR 변수 이름이고 활성 FOR 변수 이름 인 후속 문자가있는 경우 해당 문자는 수정 자로 해석됩니다.
- FOR 변수 이름은 전역이지만 DO 절의 컨텍스트 내에서만 사용됩니다. FOR DO 절에서 루틴이 호출되면 FOR 변수는 호출 된 루틴 내에서 확장되지 않습니다. 그러나 루틴에 자체 FOR 명령이 있으면 현재 정의 된 모든 FOR 변수가 내부 DO 명령에 액세스 할 수 있습니다.
- FOR 변수 이름은 중첩 된 FOR 내에서 재사용 할 수 있습니다. 내부 FOR 값이 우선하지만 INNER FOR가 닫히면 외부 FOR 값이 복원됩니다.
- 이 단계가 시작될 때 ECHO가 ON이면 FOR 변수가 확장 된 후 구문 분석 된 DO 명령을 표시하기 위해 3) 단계가 반복됩니다.
----이 시점부터 2 단계에서 식별 된 각 명령이 별도로 처리됩니다.
---- 다음 명령으로 넘어 가기 전에 한 명령에 대해 5-7 단계가 완료됩니다.
5 단계) 지연 확장 : 지연 확장이 켜져있는 경우에만 명령이 파이프의 양쪽 에있는 괄호로 묶이지 않은 블록에 없고 명령이 "네 이크"배치 스크립트 가 아닙니다 (괄호없는 스크립트 이름, CALL, 명령 연결, 또는 파이프).
- 명령에 대한 각 토큰은 확장 지연에 대해 독립적으로 구문 분석됩니다.
- 대부분의 명령은 둘 이상의 토큰 (명령 토큰, 인수 토큰 및 각 리디렉션 대상 토큰)을 구문 분석합니다.
- FOR 명령은 IN 절 토큰 만 구문 분석합니다.
- IF 명령은 비교 연산자에 따라 하나 또는 두 개의 비교 값만 구문 분석합니다.
- 구문 분석 된 각 토큰에 대해 먼저 토큰이 포함되어 있는지 확인하십시오
!
. 그렇지 않은 경우 토큰이 구문 분석되지 않으며 ^
문자에 중요 합니다. 토큰에가 포함되어 있으면 !
왼쪽에서 오른쪽으로 각 문자를 스캔하십시오.
- 캐럿 (
^
) 인 경우 다음 문자에 특별한 의미가 없으면 캐럿 자체가 제거됩니다.
- 느낌표 인 경우 다음 느낌표 (카레 트가 더 이상 표시되지 않음)를 검색하고 변수 값으로 확장하십시오.
- 연속적인 개구부
!
가 단일로 축소됩니다!
- 페어링되지 않은 나머지
!
는 제거됩니다
- 특수 문자가 발견되지 않기 때문에이 단계에서 바르 확장은 더 이상, (심지어 "안전"입니다
<CR>
또는 <LF>
)
- 더 완전한 설명을 보려면 dbenham same thread-Exclamation Point Phase 에서 후반부를 읽으십시오.
단계 5.3) 파이프 처리 : 명령이 파이프의 양쪽에있는 경우에만 파이프의
각 측면은 독립적으로 비동기 적으로 처리됩니다.
- 명령이 cmd.exe의 내부이거나 배치 파일이거나 괄호로 묶인 명령 블록 인 경우을 통해 새 cmd.exe 스레드에서 실행
%comspec% /S /D /c" commandBlock"
되므로 명령 블록이 단계를 다시 시작하지만 이번에는 명령 행 모드에서.
- 괄호로 묶인 명령 블록 인 경우
<LF>
이전과 이후에 명령이있는 모든 항목 이로 변환됩니다 <space>&
. 다른 사람 <LF>
은 제거됩니다.
- 이것이 파이프 명령 처리의 끝입니다.
- 파이프 된 코드 블록 내부에서 확장 지연이 실패하는 이유는 무엇입니까?를 참조하십시오 . 파이프 구문 분석 및 처리에 대한 자세한 내용
단계 5.5) 리디렉션 실행 : 이제 2 단계에서 검색된 리디렉션이 실행됩니다.
단계 6) CALL 처리 / 카트 배가 : 명령 토큰이 CALL이거나 첫 번째 표준 토큰 분리 문자 앞의 텍스트가 CALL 인 경우에만 해당됩니다. 더 큰 명령 토큰에서 CALL을 구문 분석하는 경우, 사용하기 전에 사용하지 않은 부분이 인수 토큰 앞에 추가됩니다.
- 따옴표없는 인수 토큰을 스캔하십시오
/?
. 토큰 내에서 발견 된 경우 6 단계를 중단하고 7 단계로 진행하여 CALL HELP for CALL이 인쇄됩니다.
- 첫 번째를 제거하면
CALL
여러 개의 CALL을 쌓을 수 있습니다
- 모든 캐럿 두 배
- 1, 1.5 및 2 단계를 다시 시작하지만 3 단계를 계속하지 마십시오
- 배가 된 캐럿은 인용되지 않은 한 캐럿으로 다시 축소됩니다. 그러나 불행하게도 인용 된 캐럿은 두 배로 남아 있습니다.
- 1 단계가 약간 변경됨
- 1.2 또는 1.3 단계의 확장 오류는 CALL을 중단하지만 오류는 치명적이지 않습니다. 일괄 처리가 계속됩니다.
- 2 단계 작업이 약간 변경됨
- 2 단계의 첫 번째 라운드에서 발견되지 않은 새로 표시되고 인용되지 않은 이스케이프되지 않은 리디렉션이 감지되지만 실제로 리디렉션을 수행하지 않고 제거됩니다 (파일 이름 포함).
- 줄 끝에서 새로 표시되고 인용되지 않은 이스케이프되지 않은 캐럿은 줄 연속을 수행하지 않고 제거됩니다.
- 다음 중 하나라도 감지되면 오류없이 통화가 중단됩니다.
- 인용되지 않은, 이스케이프되지 않은
&
또는|
- 결과 명령 토큰은 인용되지 않고 이스케이프되지 않은 것으로 시작합니다
(
- 제거 된 CALL이 시작된 후 첫 번째 토큰
@
- 결과 명령이 겉보기에 유효한 IF 또는 FOR 인 경우 내부 또는 외부 명령으로 인식
IF
되거나 FOR
인식되지 않는 오류와 함께 실행이 실패 합니다.
- 결과 명령 토큰이로 시작하는 레이블 인 경우 2 단계의이 2 차 라운드에서 CALL이 중단되지 않습니다
:
.
- 결과 명령 토큰이 CALL 인 경우 6 단계를 다시 시작하십시오 (CALL이 더 이상 없을 때까지 반복).
- 결과 명령 토큰이 배치 스크립트 또는 : label 인 경우 CALL 실행은 나머지 6 단계에서 완전히 처리됩니다.
- 호출이 완료 될 때 올바른 위치에서 실행을 재개 할 수 있도록 호출 스택에서 현재 배치 스크립트 파일 위치를 푸시하십시오.
- 모든 결과 토큰을 사용하여 CALL에 대해 % 0, % 1, % 2, ... % N 및 % * 인수 토큰을 설정하십시오.
- 명령 토큰이로 시작하는 레이블
:
인 경우
- 5 단계를 다시 시작하십시오. 이는 : label이 호출되는 대상에 영향을 줄 수 있습니다. 그러나 % 0 등 토큰이 이미 설정되었으므로 CALLed 루틴에 전달되는 인수는 변경되지 않습니다.
- GOTO 레이블을 실행하여 서브 루틴의 시작 부분에 파일 포인터를 배치하십시오 (: label 다음에 오는 다른 토큰은 무시하십시오) GOTO 작동 방식에 대한 규칙은 7 단계를 참조하십시오.
- 지정된 배치 스크립트로의 다른 전송 제어.
- CALLed : label 또는 script의 실행은 EXIT / B 또는 파일 끝에 도달 할 때까지 계속됩니다.이 시점에서 CALL 스택이 팝업되고 저장된 파일 위치에서 실행이 재개됩니다.
콜드 스크립트 또는 : labels에 대해서는 7 단계가 실행되지 않습니다.
- 그렇지 않으면 6 단계의 결과는 실행을 위해 7 단계로 넘어갑니다.
단계 7) 실행 : 명령이 실행됩니다
- 7.1-내부 명령 실행 -명령 토큰이 인용 된 경우이 단계를 건너 뜁니다. 그렇지 않으면 내부 명령을 구문 분석하고 실행하십시오.
- 인용되지 않은 명령 토큰이 내부 명령을 나타내는 지 확인하기 위해 다음 테스트가 수행됩니다.
- 명령 토큰이 내부 명령과 정확히 일치하면 실행하십시오.
- 그렇지 않으면 처음 발생하기 전에 명령 토큰을 끊
+
/
[
]
<space>
<tab>
,
;
거나 =
이전 텍스트가 내부 명령 인 경우 해당 명령을 기억하십시오.
- 명령 행 모드에 있거나 명령이 괄호로 묶인 블록, IF true 또는 false 명령 블록, FOR DO 명령 블록에 있거나 명령 연결과 관련된 경우 내부 명령을 실행하십시오.
- 그렇지 않으면 (일괄 처리 모드에서 독립 실행 형 명령이어야 함) 현재 폴더와 PATH에서 기본 이름이 원래 명령 토큰과 일치하는 .COM, .EXE, .BAT 또는 .CMD 파일을 검색합니다.
- 첫 번째로 일치하는 파일이 .BAT 또는 .CMD 인 경우 7.3.exec로 이동하여 해당 스크립트를 실행하십시오.
- 그렇지 않으면 (일치를 찾을 수 없거나 첫 번째로 일치하는 것이 .EXE 또는 .COM 임) 기억 된 내부 명령을 실행하십시오.
- 그렇지 않으면 첫 번째 발생 전에 명령 토큰을 끊
.
\
거나 :
이전 텍스트가 내부 명령이 아닌 경우 7.2로
가십시오. 그렇지 않으면 이전 텍스트가 내부 명령 일 수 있습니다. 이 명령을 기억하십시오.
- 첫 번째 발생 전에 명령 토큰을 중단하십시오.
+
/
[
]
<space>
<tab>
,
;
또는 =
이전 텍스트가 기존 파일의 경로 인 경우 7.2로
이동하여 기억 된 내부 명령을 실행하십시오.
- 더 큰 명령 토큰에서 내부 명령을 구문 분석하면 명령 토큰의 사용되지 않은 부분이 인수 목록에 포함됩니다.
- 명령 토큰이 내부 명령으로 구문 분석되었다고해서 성공적으로 실행되는 것은 아닙니다. 각 내부 명령에는 인수와 옵션을 구문 분석하는 방법과 허용되는 구문에 대한 자체 규칙이 있습니다.
- 모든 내부 명령
/?
은 감지 된 경우 기능을 수행하는 대신 도움말을 인쇄 합니다. /?
인수의 어느 곳에 나 나타나는지 대부분을 인식 합니다. 그러나 ECHO 및 SET와 같은 몇 가지 명령은 첫 번째 인수 토큰이로 시작하는 경우에만 도움말을 인쇄합니다 /?
.
- SET에는 몇 가지 흥미로운 의미가 있습니다.
- 변수 이름과 확장명을 활성화하기 전에 SET 명령에 따옴표가 있으면
set "name=content" ignored
-> value = content
첫 번째 등호와 마지막 따옴표 사이의 텍스트가 내용으로 사용됩니다 (첫 번째 등호와 마지막 따옴표는 제외). 마지막 따옴표 뒤의 텍스트는 무시됩니다. 등호 뒤에 따옴표가 없으면 나머지 줄이 내용으로 사용됩니다.
- SET 명령에 이름
set name="content" not ignored
-> value = 앞에 따옴표가 없으면 "content" not ignored
등호 다음에 나오는 줄의 나머지 부분이 모든 따옴표를 포함하여 내용으로 사용됩니다.
- IF 비교가 평가되고 조건이 참인지 거짓인지에 따라 5 단계부터 시작하여 적절한 구문 분석 된 종속 명령 블록이 처리됩니다.
- FOR 명령의 IN 절이 적절하게 반복됩니다.
- 이것이 명령 블록의 출력을 반복하는 FOR / F 인 경우 :
- IN 절은 CMD / C를 통해 새 cmd.exe 프로세스에서 실행됩니다.
- 명령 블록은 두 번째로 전체 구문 분석 프로세스를 거쳐야하지만 이번에는 명령 행 컨텍스트에서 수행해야합니다.
- ECHO는 ON으로 시작하고 지연된 확장은 일반적으로 비활성화됩니다 (레지스트리 설정에 따라)
- 하위 cmd.exe 프로세스가 종료되면 IN 절 명령 블록에 의해 작성된 모든 환경 변경 사항이 유실됩니다.
- 각 반복에 대해 :
- FOR 변수 값이 정의됩니다
- 그런 다음 이미 구문 분석 된 DO 명령 블록이 단계 4부터 시작하여 처리됩니다.
- GOTO는 다음 로직을 사용하여 : label을 찾습니다.
- 첫 번째 인수 토큰에서 레이블이 구문 분석됩니다.
- 다음 번에 나타나는 레이블에 대해 스크립트를 스캔합니다.
- 스캔은 현재 파일 위치에서 시작합니다
- 파일의 끝에 도달하면 스캔은 파일의 시작 부분으로 되돌아 가고 원래 시작점으로 계속됩니다.
- 발견 된 레이블이 처음 발견되면 스캔이 중지되고 파일 포인터는 레이블 바로 다음 줄로 설정됩니다. 이 시점부터 스크립트 실행이 재개됩니다. 성공적인 true GOTO는 FOR 루프를 포함하여 구문 분석 된 코드 블록을 즉시 중단합니다.
- 레이블을 찾을 수 없거나 레이블 토큰이 없으면 GOTO가 실패하고 오류 메시지가 인쇄되며 호출 스택이 팝업됩니다. 이것은 GOTO를 따르는 현재 명령 블록에서 이미 구문 분석 된 명령이 여전히 실행되지만 CALLer의 컨텍스트 (EXIT / B 뒤에 존재하는 컨텍스트)를 제외하고는 EXIT / B로 효과적으로 작동합니다.
- 레이블 구문 분석에 사용되는 규칙에 대한 자세한 설명은 https://www.dostips.com/forum/viewtopic.php?f=3&t=3803 을 참조 하십시오 .
- RENAME 및 COPY는 모두 소스 및 대상 경로에 와일드 카드를 허용합니다. 그러나 Microsoft는 와일드 카드가 작동하는 방식, 특히 대상 경로에 대해 끔찍한 작업을 수행합니다. 유용한 와일드 카드 규칙 세트 는 Windows RENAME 명령이 와일드 카드를 어떻게 해석합니까? 에서 찾을 수 있습니다 .
- 7.2-볼륨 변경 실행 -그렇지 않으면 명령 토큰이 따옴표로 시작하지 않고 정확히 두 문자 길이이고 두 번째 문자가 콜론 인 경우 볼륨을 변경하십시오.
- 모든 인수 토큰은 무시됩니다
- 첫 번째 문자로 지정된 볼륨을 찾을 수 없으면 오류와 함께 중단하십시오
::
SUBST를 사용하여 볼륨을 정의하지 않는 한의 명령 토큰 은 항상 오류가 발생합니다. SUBST를 사용하여 볼륨을 정의하는 ::
경우 ::
볼륨이 변경되면 레이블로 처리되지 않습니다.
- 7.3-외부 명령 실행 -그렇지 않으면 명령을 외부 명령 으로 취급하십시오.
- 커맨드 라인 모드와 명령에서 인용되지 않고 볼륨 사양, 공백로 시작하지 않으면,
,
, ;
, =
또는 +
다음의 첫 번째 항목에서 토큰 명령 중단 <space>
,
;
또는 =
과 (들) 토큰 인수에 나머지를 앞에 추가.
- 명령 토큰의 두 번째 문자가 콜론 인 경우 첫 번째 문자로 지정된 볼륨을 찾을 수 있는지 확인하십시오.
볼륨을 찾을 수 없으면 오류와 함께 중단하십시오.
- 배치 모드에서 명령 토큰이로 시작
하면
:
7.4로 이동
하십시오. 레이블 토큰이로 시작하면 ::
SUBST를 사용하여 볼륨을 정의하지 않는 한 이전 단계에서 오류가 발생하여이 단계에 도달하지 못합니다 ::
.
- 실행할 외부 명령을 식별하십시오.
- 이것은 현재 볼륨, 현재 디렉토리, PATH 변수, PATHEXT 변수 및 / 또는 파일 연관을 포함 할 수있는 복잡한 프로세스입니다.
- 유효한 외부 명령을 식별 할 수 없으면 오류와 함께 중단하십시오.
- 커맨드 라인 모드로 시작 토큰 명령의 경우
:
, 다음 고토 7.4
명령 토큰으로 시작하지 않는 한 이전 단계가 오류로 중단 한 것 때문에 거의 도달되지 않도록주의 ::
하고, SUBST를위한 볼륨을 정의하는 데 사용 ::
하고, 전체 명령 토큰은 외부 명령의 유효한 경로입니다.
- 7.3.exec- 외부 명령을 실행합니다.
- 7.4-레이블 무시-명령 토큰이로 시작하면 명령과 모든 인수를 무시하십시오
:
.
7.2 및 7.3의 규칙에 따라 라벨이이 지점에 도달하지 못할 수 있습니다.
커맨드 라인 파서 :
다음을 제외하고 BatchLine-Parser와 같이 작동합니다.
1 단계) 확장 비율 :
- 아니
%*
, %1
등 인수 확장
- var가 정의되지 않은 경우
%var%
변경되지 않은 상태로 유지됩니다.
- 특별한 취급은 없습니다
%%
. var = content이면로 %%var%%
확장됩니다 %content%
.
3 단계) 파싱 된 명령 에코
- 2 단계 이후에는 수행되지 않으며 FOR DO 명령 블록의 4 단계 이후에만 수행됩니다.
5 단계) 지연 확장 : DelayedExpansion이 활성화 된 경우에만
- var가 정의되지 않은 경우
!var!
변경되지 않은 상태로 유지됩니다.
7 단계) 명령 실행
- : label을 호출하거나 GOTO하려고하면 오류가 발생합니다.
- 7 단계에서 이미 설명한 바와 같이, 실행 된 레이블은 다른 시나리오에서 오류가 발생할 수 있습니다.
- 배치 실행 레이블은 다음으로 시작하는 경우에만 오류를 일으킬 수 있습니다.
::
- 명령 행에서 실행 된 레이블은 거의 항상 오류를 발생시킵니다
정수 값 파싱
cmd.exe가 문자열의 정수 값을 구문 분석하는 규칙에는 여러 가지가 있으며 규칙이 일치하지 않습니다.
SET /A
IF
%var:~n,m%
(가변 부분 문자열 확장)
FOR /F "TOKENS=n"
FOR /F "SKIP=n"
FOR /L %%A in (n1 n2 n3)
EXIT [/B] n
이러한 규칙에 대한 자세한 내용은 CMD.EXE가 숫자를 구문 분석하는 방법에 대한 규칙 에서 찾을 수 있습니다.
cmd.exe 구문 분석 규칙을 개선하려는 사람은 DosTips 포럼 에 문제를보고하고 제안 할 수 있는 토론 주제가 있습니다.
희망이 도움이
월 에릭 (젭) - 단계의 원래 저자 및 발견을
데이브 벤함 (Benham) (dbenham) - 많은 추가 콘텐츠 및 편집