쉘 스크립트-예기치 않은 토큰`else '근처의 구문 오류


15

다음 셸 스크립트를 사용하면 왜 오류가 발생합니까?

syntax error near unexpected token `else'

쉘 스크립트

echo "please enter username"
read user_name
echo "please enter password"
read -s pass
echo ${ORACLE_SID}
SID=${ORACLE_SID}
if ["${ORACLE_SID}" != 'Test'] then
sqlplus -s -l $USER_NAME/$PASS@$SID <<EOF
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
EOF
else
echo "Cannot copy"
fi


현재 표시하지 않으려는 것을 표시 할 수 있으므로 "copy from ...."행을 편집 할 수 있습니다. (그러나 나는 그들이 현명한 보안 현명하지 않기 때문에 이미 수정 된 정보를 희망합니다)
Olivier Dulac

1
@OlivierDulac 해당 라인에서 사용자 이름과 비밀번호를 참조하는 경우 모든 Oracle 데이터베이스 사용자에게 알려집니다. Oracle 데이터베이스가 시작된 이래 일반적이며 잘 알려져 있습니다.
Jåcob

답변:


25

다음 if과 같은 조건을 종료해야합니다 .

if [ "${ORACLE_SID}" != 'Test' ]; then

또는 이와 같이 :

if [ "${ORACLE_SID}" != 'Test' ]
then

참고 : 또한 공백을 넣어야합니다. [ 하고 전에 ].

;또는 줄 바꿈 의 이유 는 if명령문 의 조건 부분이 명령 일뿐입니다. 모든 길이의 명령이 정확해야합니다. 셸은 해당 명령을 실행하고 명령의 종료 상태를 검사 한 다음 then부품 을 실행할지 여부를 결정합니다 else.

명령은 길이가 길 수 있으므로 조건 부분의 끝을 표시하는 마커가 있어야합니다. 그 ;개행 문자 또는 개행 문자 다음에 then.

공백이 발생한 [이유 [는 명령 때문 입니다. 일반적으로 쉘 내장. 쉘은 마지막 필수 [매개 변수를 포함하여 나머지를 매개 변수로 사용 하여 명령 을 실행합니다 ]. [쉘 뒤에 공백을 넣지 않으면 [whatever명령 으로 실행 을 시도 하고 실패합니다.

이전의 공간에 대한 이유 ]는 비슷합니다. 그렇지 않으면 자체 매개 변수로 인식되지 않기 때문입니다.


그 자리에 있었지만 지금은 test.sh: line 6: [: missing
나옵니다

@lesmana. 잘못된 답변을 먼저 제공 한 다음 다른 사람이 올바른 답변을 제공하기 전에 계속 수정하는 좋은 방법입니다. 처음에 정답을 제공하십시오.
Valentin Bajrami

1
첫 대답이 잘못되었다고 생각하지 않습니다. 실제로, 그것은 "현장에"있었습니다. 그것은 문제의 모든 문제를 해결하지 못했습니다 .
lesmana

if 이다 는 일반 명령하지 않습니다, 구문. 예약어입니다. 다른 많은 프로그래밍 언어와는 달리, 쉘은 예약어가 명령의 첫 단어 일 때만 (어려움이 거의 없음) 예약어를 인식하지 못합니다.
Gilles 'SO- 악한 중지'

설명 주셔서 감사합니다. 나는 그것이 if구문 이라는 것을 알고 있습니다. 의 조건 부분이 if구문에 의해 특정 형식으로 제한되지 않는다는 것을 알리려고했습니다. 텍스트를 편집했습니다. 나는 그것이 더 명확 해지기를 바랍니다.
lesmana

5

온라인 ShellCheck 를 사용하여 쉘 스크립트를 쉽게 확인할 수 있습니다 (독립형 도구로도 사용 가능).

이 경우, 만약 문 후 공간, 필요가 있다고 지적합니다 [그리고 전에 ]당신이 필요하고, 그 ;전과 (또는 줄 바꿈)를 then같은 줄에.

당신이 그것을 고치면, 그것은 USER_NAME아무것도 초기화되지 않고 사용 되었음을 알려줍니다 . user_name변수 (사건) 도 있기 때문 입니다. PASS및에 대해서도 마찬가지입니다 pass.

또한 맹 글링 read -r을 멈추는 데 사용 하고 (예를 들어 암호에 중요 할 수 있음) 쉘이 실수로 파일 이름 globbing 및 단어 분리를 수행하지 않도록 호출 할 때 변수를 큰 따옴표로 묶어야한다고 알려줍니다 (다시 중요한 경우 예를 들어, 비밀번호에는 , 또는 공백 과 같은 파일 글 로빙 문자가 포함됩니다 .read\sqlplus*

코드를 들여 쓰면 더 읽기 쉽다 :

#!/bin/bash

read -r -p 'please enter username: ' user_name
IFS= read -rs -p 'please enter password: ' pass

printf 'ORACLE_SID = %s\n' "$ORACLE_SID"
sid=$ORACLE_SID

if [ "$sid" = 'Test' ]; then
    echo 'Cannot copy' >&2
    exit 1
fi

sqlplus -s -l "$user_name/$pass@$sid" <<'SQL_END'
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
SQL_END

여기 IFS에서 비밀번호 읽기를 위해 빈 문자열 로 임시 설정 하여 선행 또는 후행 공백 문자와 함께 비밀번호를 사용할 수도 있습니다 read.

$ORACLE_SID/ $sid가 있으면 논리가 구제되도록 변경되었습니다 Test. 이렇게하면 스크립트의 주요 운영 부분이 if브랜치에 포함되지 않습니다.


참고 if ([ x = x ]) then (echo yes) fi도 작동합니다.
Stéphane Chazelas

@ StéphaneChazelas 아, 그렇습니다. 그리고 그것은 쉘 코드를 생성하는 프로그램의 관점에서 흥미로울 수 있지만, 일반적 if으로 [ ... ]... :-)를 사용 하여 문장을 작성하는 방법은 아닙니다.
Kusalananda

2

sh을 쓸 때

if [ "$ORACLE_SID" != "Test" ]
then
  ...
fi

쓸 때 bash

if [[ "$ORACLE_SID" != "Test" ]]
then
  ...
fi

빈칸 좀주세요 [[첫 번째 연산자 사이에 공백이 있어야합니다 .

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