노무현 대통령 배너
BLOG main image
왕미친놈의 왕미친세상입니다. 미친 소리는 써도 되지만, 근거 없는 소리는 쓰면 안 됩니다.


아크로에디트snoopy 님윈도우 7 언어팩 통합/삭제 가이드에 나타난 사항을 배치파일로 만들다가 벌레를 하나 발견하였다.

벌레의 유형

단순히 화면 출력을 잘못하는 벌레로 여겨졌다.

하지만 문법 강조에 관한 기능을 살펴본 끝에 대부분 아크로 에디트에 사는 벌레가 아니라, 처음에 문법 강조를 만들 때 해당 문법 강조 설정에 숨어 있던 벌레로 판명났다. 이 설정 파일은 내가 만든 것이 아니라 마소리스 님이 만든 것을 수정해서 쓰고 있었고, 거기에 숨어 있던 벌레였다. 물론 마지막에 가서 아크로에디트에 사는 벌레 하나를 찾을 수 있었다.

벌레 정보

  • 아크로에디트 버전 0.9 / 빌드 0.9.19.84 (2008년 12월 17일자)에서 발견하였고, 이전 버전 확인하지 못하였다.
  • 배치파일 구문 강조에서 나타났다.

벌레의 발견

배치 파일에서 "ECHO Do you want to remove other language package ? [Y/n]"라는 명령문을 입력했다가 다음과 같이 나타나서 벌레가 있음을 알게 되었다.

배치파일 문법 강조 오류

배치파일 문법 강조에서 rem이 나온 행에서 그 뒤로는 모두 주석으로 인식되는 벌레가 있다.

이때 배치파일 문법 강조 설정은 다음과 같다.

배치파일 문법 강조 설정

배치파일 문법 강조 설정.

위에서 보다시피 배치파일 문법 강조에서 행 주석으로 "rem"과 "REM"은 인식하도록 했다(파란색 네모 부분). 그런데 이 부분에서 무언가 잘못된 처리를 하고 있기 때문에 벌레가 나타난다고 여겨진다.

정말로 벌레인가? 1

아무튼 첫 번째 그림에서 129행 부분만을 떼어 내어 여러 가지 측면에서 살펴보았다.

예제 1-1. 맨 처음 발견한 벌레

예제 1-1. 맨 처음 발견한 벌레

예제 1-2. 대문자로 바꾸어도 마찬가지

예제 1-2. 대문자로 바꾸어도 마찬가지

예제 1-3. 큰따옴표(

예제 1-3. 큰따옴표(

예제 1-4. 작은따옴표(' ')로 묶어도 마찬가지

예제 1-4. 작은따옴표(' ')로 묶어도 마찬가지

예제 1-3과 1-4에서는 조금 뜻밖이었다. 보통 큰따옴표나 작은따옴표로 묶이면 문자열로 인식하고, 그럼으로써 행 주석 기호가 인식되지 않아야 하기 때문이다. 그래서 현재의 배치파일 문법 강조 설정에서 문자열 시작 문자(빨간색 네모 부분)에 "' (큰따옴표와 작은따옴표를 연속으로 입력)라고 지정함으로써 예제 1-3과 1-4를 해결하였다. 그 그림은 다음과 같다.

예제 2-1. 작은따옴표로 문자열 처리

예제 2-1. 작은따옴표로 문자열 처리

예제 2-1. 큰따옴표로 문자열 처리

예제 2-1. 큰따옴표로 문자열 처리

결국 예제 1-1과 1-2는 벌레로 여겨지지만, 예제 1-3과 1-4는 벌레가 아니었다.

정말로 벌레인가? 2

앞서 벌레로 여겨진 예제 1-1과 1-2를 다시 살펴보자.

예제 1-1. 맨 처음 발견한 벌레

예제 1-1. 맨 처음 발견한 벌레

여기에서 하나 짚고 넘어가야 할 문제가 있었다. 바로 배치파일에서 행 주석을 나타내는 지시어인 REM명령어라는 사실이다. 이게 왜 중요하냐고? 명령어 다음에 한 칸 이상의 공백이 있어야 하기 때문에 중요하다.

수정한 배치파일 문법 강조 설정

수정한 배치파일 문법 강조 설정.

위의 그림처럼 행 주석을 "rem"과 "REM"에서 "rem "과 "REM "(뒤에 공백 한 칸 있음)로 바꾸었다.

예제 3-1.

예제 3-1.

예제 3-2.

예제 3-2.

에제 3-2에서는 왜 주석으로 인식될까? 이는 당연하다. 명령어처럼 인식하도록 뒤에 공백을 넣었지만, 실제로 명령어 인식되지는 않았기 때문이다. 아크로에디트를 수정하지 않고 문법 강조 설정을 수정해서는 여기가 한계인 셈이다.

아무튼 예제 3-2에서 아크로에디트가 가진 벌레 하나를 찾을 수 있었다.

또 다른 상황

아크로에디트 구문 강조 오류 문서에서 살펴본 벌레를 상기하자. 그 글에서는 아크로에디트에서 rEm 등이 주석으로 처리되지 않는 벌레가 있음을 보였다. 여기에서도 그 벌레가 적용되는지를 살펴보았다.

예제 4-1.

예제 4-1.

예제 4-2.

예제 4-2.

벌레와 벌레가 만나자 한쪽은 작동하지 못하게 되었다.

파일

마소리스 님이 만든 배치파일 문법 강조 파일은 더 이상 유효하지 않다고 생각하여 이번에 수정한 파일을 첨부한다.

  • batch.stx (5174 바이트)
  • CRC32 : 857C74D9
  • MD5 : ac9cc62baa2f4d56330eef3449b45101
  • SHA : ab6d03405ff9c649f15ec5bb65745ad2006ff66b

제작자/제공자의 답변

2009년 5월 16일 현재 AcroEdit - 질문 및 답변에 글을 올린 상태이다.

관련 문서

내부 문서

외부 문서

이 글은 스프링노트에서 작성되었습니다.


글쓴이는 koc/SALM입니다.
본문에 저작권에 대한 사항이 나타나지 않거나, 저작권이 BY-SA로 표기되어 있다면,
이 글은 GFDL로 공개한 글입니다.

들어가며

IF 문자열 비교 구문은 말 그대로 문자열을 비교하는 구문이다. 이것은 윈도NT 계열에서 추가된 환경 변수 등을 이용하여 여러 가지 작업을 할 수 있도록 해준다. 문자열의 내용을 분석하여 정수(십진수, 팔진수, 십육진수)로 변환하여 계산해 주기도 한다.

말뜻

IF 문자열 비교 구문에서는 일반적으로 등호를 두 개 겹쳐서 쓰게 된다.

  1. if [not] 문자열1==문자열2 명령 [else 구문]

위와 같은 형식을 이루게 된다. 이때 큰괄호( [ ] )로 묶인 부분은 반드시 쓸 필요는 없고 필요할 때 쓰면 된다. 또한 문자열에 공백을 포함하지 않았다면 따옴표를 사용하지 않아도 된다.

문자열 비교 구문의 명령 확장

확장 1

명령 확장이라고 말하기는 했으나, 사실 /i 선택자는 cmd.exe에 포함된 if 명령에서는 기본 선택자이다. 다만 도스의 if 명령과 호환성이 없기 때문에 확장이라고 칭했을 뿐이다.

문자열 비교 구문에서 /i 선택자를 쓰게 되면 그 기능을 확장할 수 있다. 이것은 대문자와 소문자를 무시하고 문자열을 비교하게 됩니다.

  1. IF STRING==string ECHO STRING is string.

위의 문자열 비교 구문은 거짓을 돌려주므로 화면에 아무것도 보여주지 않는다. 그러나 아래 문자열 비교 구문은 참을 돌려주므로 화면에 "STRING is string."이라는 문자열을 출력해 준다.

  1. IF /i STRING==string ECHO STRING is string.

확장 2

문자열 비교 구문에서는 세 문자로 이루어진 비교 연산자를 사용할 수 있다. 이것은 /i 선택자를 사용하여 융통성을 가지는데, 예컨대 숫자로만 이루어진 문자열은 수로 변환하여 비교해 준다.

세 문자로 이루어진 비교 연산자에는 다음과 같은 것이 있다.

  • EQU (같음)
  • NEQ (같지 않음)
  • LSS (보다 작음)
  • LEQ (작거나 같음)
  • GTR (보다 큼)
  • GEQ (크거나 같음)

비교 연산자는 언뜻 보아서는 숫자로 이루어진 문자열에만 쓰일 듯이 보이지만 로마자 등으로 이루어진 문자열에도 쓰일 수 있다.

예제 1

  1. IF /i 22 EQU 026 ECHO 22 is 026.

위의 코드는 10진수 22와 8진수 026을 비교하는 구문이다. 당연히 두 값은 크기가 같으므로 화면에 문자열을 출력해 준다.

  1. IF /i 026 EQU 0X16 ECHO 026 is 0X16.

위의 코드는 8진수 026과 16진수 0x16을 비교하는 구문이다. 당연히 두 값은 크기가 같으므로 화면에 문자열을 출력해 준다. 

두 예제는 /i 선택자가 문자열을 확장하여 "일반적으로 해석"하는 예시이다. 다시 말해 문자열 22는 10진수 22로 해석해 주며, 026은 8진수로, 0x16은 16진수로 해석해 준다. 10진수는 0으로 시작할 수 없으며, 0으로 시작하는 수는 8진수이거나 16진수가 된다. 또한 0으로 시작하는 문자열 가운데 0x로 시작하는 문자열은 16진수로 여기게 된다.

하지만 089 등의 문자열은 올바르지 않으므로 오류가 발생하게 된다. 이는 8진수에 8과 9와 같은 숫자는 존재하지 않기 때문이다. 마찬가지로 0x9G 등의 문자열도 올바르지 않다고 여긴다. 이럴 경우 문자열을 수로 확장해 주지 않고, 문자열 자체(리터럴 문자열)로서 비교하게 된다. 참고로 순수한 문자열을 리터럴 문자열(literal string), 수치로서 변환되는 문자열을 숫자 문자열(number string / numeric string)이라고 부른다.

한편 다음에 오는 두 비교문은 서로 다른 결과를 가진다.

  1. IF /i 22 EQU 026 ECHO 22 is 026.

위의 비교문은 수치 비교문으로 참값을 돌려주므로 "22 is 026."을 출력한다.

  1. IF /i 22 == 026 ECHO 22 is 026.

위의 비교문은 리터럴 문자열 비교문으로 거짓값을 돌려주므로 아무것도 출력하지 않는다.

다시 말해 숫자로 이루어진 문자열을 숫자 문자열로서 비교하려면 반드시 문자로 이루어진 비교 연산자를 사용해야 한다.

또한 다음과 같이 사용할 수도 있다.

  1. IF /i abc EQU ABC ECHO abc is ABC.

또는

  1. IF /i NOT abc EQU ABC ( ECHO abd is ABC ) ELSE ECHO abd is not ABC .

앞서 말했듯이 세 문자로 이루어진 비교 연산자로 숫자 문자열뿐만 아니라 리터럴 문자열까지 비교할 수 있다.

  1. IF /i abc NEQ ABC ( ECHO abd is ABC ) ELSE ECHO abd is not ABC .

위의 비교문도 정상 작동한다.

예제 2

그렇다면 작거나 같음을 비교할 때는 어떻게 동작할까? LSS (보다 작음), LEQ (작거나 같음), GTR (보다 큼), GEQ (크거나 같음)과 같은 세 문자로 이루어진 비교 연산자를 이용하여 대문자와 소문자를 비교해 보자,

  1. IF /i 22 LSS 027 ECHO 22 is less than 027.

위 예제는 10진수 22가 8진수 027보다 작으면 뒤따르는 문자열을 출력하라는 문자열 비교문입니다.

그러면 다음과 같은 두 가지 예문은 어떻게 작동할까?

  1. IF /i abc LSS ABC ECHO abc is less than ABC.
  2. IF abc LSS ABC ECHO abc is less than ABC.

우선 1행은 아무런 출력이 없다. 왜냐하면 /i 선택자 때문에 대문자와 소문자를 무시하고 비교했기 때문이다. 그러나 2행은 소문자 abc가 대문자 ABC보다 더 작은 값으로 해석되어 문자열 "abc is less than ABC."을 출력해 준다.

  1. IF ABC GTR abc ECHO ABC is greater than abc.

마찬가지로 위의 코드는 대문자 ABC가 소문자 abc보다 더 큰 값으로 해석되어 "ABC is greater than abc."라는 문자열을 출력해 준다.

위와 같이 대문자와 소문자 비교에서 대문자가 소문자보다 더 크다고 판정함을 알 수 있다.

예제 3

그 다음으로 문자간 비교를 해볼 수 있다.

  1. IF d GTR a ECHO D is greater than A.

위의 예제는 문자여을 출력해 준다. 다시 말해 문자열 d가 문자열 a보다 더 큰 값을 가진다고 판단함을 알 수 있다. 반대로 아래와 같은 비교문도 성립한다.

  1. IF a LSS d ECHO a is less than d.

로마자 알파벳을 비교할 때 순서가 빠른 문자를 더 작다고 판단함을 알 수 있다.

  1. IF 가 LSS 나 ECHO 가 is less than 나.

한글 문자열을 비교할 때도 성립한다.

  1. IF 가 LSS d ECHO 가 is less than d.

한글을 로마자보다 더 작다고 판정하고 있다.

과제

아무도 검사하지 않는 과제가 또 나왔습니다. 헤헤 ^^a

  1. rem Compare.cmd
  2. IF /i NOT %1 EQU %2 ECHO %1 is equal %2 ELSE ECHO %1 is not equal %2 .

위의 배치 파일이 정상적으로 작동하도록 고쳐 보자.

다음 예고

IF 명령을 하나씩 짚어보자. (4) : IF 명령확장

이 글은 스프링노트에서 작성되었습니다.

'스크립트 > 배치파일' 카테고리의 다른 글

GOTO 명령  (3) 2009.05.05
IF 명령 확장  (1) 2009.04.22
IF EXIST  (0) 2009.04.15
IF ERRORLEVEL에 쓰이는 종료코드  (12) 2009.04.14
IF 기본 설명  (6) 2009.04.09
글쓴이는 koc/SALM입니다.
본문에 저작권에 대한 사항이 나타나지 않거나, 저작권이 BY-SA로 표기되어 있다면,
이 글은 GFDL로 공개한 글입니다.

카테고리

분류 전체보기 (1005)
스크립트 (22)
벌레와 팁 (126)
소프트웨어 (240)
하드웨어 (6)
이야기 (24)
말의 나무 (506)
미쳐보자 (22)
일기 (48)
아이폰 (10)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

달력

«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

글 보관함