이 연산자가 언제 다르게 수행하는지에 대해 약간 혼란 스럽습니다. bash에서 사용됩니다 (대괄호, 이중 대괄호, 괄호 및 이중 괄호).
[[ , [ , ( , ((
사람들이 다음과 같은 if 문에서 사용하는 것을 보았습니다.
if [[condition]] if [condition] if ((condition)) if (condition)
댓글
- 관련 : 단일 또는 이중 대괄호 사용 – bash
- 괄호와 대괄호는 ‘ 문서에서 검색하기 쉽지 않으며 ‘ 기능의 이름을 모르는 경우 ‘ 모든 기능을 사용할 수 있습니다.
답변
Bourne과 같은 쉘에서 if
문은 일반적으로 다음과 같습니다.
if command-list1 then command-list2 else command-list3 fi
then
절은 명령 목록이 0입니다. 종료 코드가 0이 아니면 else
절이 실행됩니다. command-list1
는 단순하거나 복잡 할 수 있습니다. 예를 들어 ;
, &
, &&
, ||
또는 줄 바꿈. 아래 표시된 if
조건은 command-list1
의 특별한 경우입니다.
-
if [ condition ]
[
는 기존test
명령의 또 다른 이름입니다.[
/test
는 표준 POSIX 유틸리티입니다. 모든 POSIX 셸에는 내장되어 있습니다 (POSIX²에서는 필요하지 않음).test
명령은 종료 코드 및if
문을 설정합니다. 그에 따라 작동합니다. 일반적인 테스트는 파일이 있는지 또는 한 숫자가 다른 숫자와 같은지입니다. -
if [[ condition ]]
bash , zsh , ksh 에서
test
¹의 새로운 업그레이드 된 변형입니다. em> yash , busybox sh 도 지원합니다.이[[ ... ]]
구문은 종료 코드와if
문은 그에 따라 작동합니다. 확장 기능 중에서 문자열이 와일드 카드 패턴과 일치하는지 테스트 할 수 있습니다 ( busybox sh 에 없음). -
if ((condition))
bash 및 zsh 도 지원하는 다른 ksh 확장 프로그램입니다. 이것은 산술을 수행합니다. 산술의 결과로 종료 코드가 설정되고
if
문이 작동합니다. rdingly. 산술 계산 결과가 0이 아니면 종료 코드 0 (참)을 반환합니다.[[...]]
와 마찬가지로이 양식은 POSIX가 아니므로 이식 할 수 없습니다. -
if (command)
이것은 서브 쉘에서 명령을 실행합니다. 명령이 완료되면 종료 코드를 설정하고
if
문이 그에 따라 작동합니다.이와 같은 하위 셸을 사용하는 일반적인 이유는 다음과 같은 부작용을 제한하기위한 것입니다.
command
command
에 셸 환경에 대한 변수 할당 또는 기타 변경이 필요한 경우. 이러한 변경은 하위 셸이 완료된 후에 유지되지 않습니다. -
if command
명령이 실행되고
if
문이 작동합니다. 종료 코드에 따라.
¹ 실제로는 명령이 아니라 일반 명령과는 별도의 구문을 가진 특수 쉘 구조이지만, 셸 구현에 따라 크게 다릅니다.
² POSIX에는 독립형 test
및 [
유틸리티를 사용할 수 있지만 [
의 경우 여러 Linux 배포판이 m으로 알려져 있습니다.
댓글
- 5 번째 옵션을 포함 해 주셔서 감사합니다. ‘이 실제로 작동하는 방식을 이해하는 열쇠이며 놀랍게도 활용률이 낮습니다.
-
[
는 실제로 내부 명령이나 기호가 아닌 바이너리입니다. 일반적으로/bin
에 거주합니다. - @JulienR. 실제로
[
는test
와 마찬가지로 내장되어 있습니다. 호환성을 위해 사용할 수있는 바이너리 버전이 있습니다.help [
및help test
를 확인하세요. - while ((isnt POSIX,
$((
즉, 산술 확장은 ‘ 혼동하기 쉽습니다. 종종 해결 방법은[ $((2+2)) -eq 4 ]
와 같은 것을 사용하는 것입니다. 조건문에서 산술을 사용하기 위해 - 이 답변을 두 번 이상 찬성 할 수 있으면 좋겠습니다. 완벽한 설명입니다.
답변
-
(…)
괄호는 서브 쉘 . 그 안에있는 것은 다른 많은 언어와 같은 표현이 아닙니다. 이는 명령 목록입니다 (외부 괄호와 마찬가지로). 이러한 명령은 별도의 하위 프로세스에서 실행되므로 괄호 안에서 수행되는 리디렉션, 할당 등은 괄호 외부에 영향을주지 않습니다. -
{ … }
중괄호는 명령을 그룹화한다는 점에서 괄호와 비슷하지만 그룹화가 아닌 구문 분석에만 영향을줍니다. 프로그램x=2; { x=4; }; echo $x
는 4를 인쇄하는 반면x=2; (x=4); echo $x
는 2를 인쇄합니다 (중괄호는 키워드 로 구분되어야하며 명령 위치에 있습니다 (따라서{
뒤의 공백 및}
앞의;
). 반면 괄호는 그렇지 않습니다. 이는 단지 구문상의 문제 일뿐입니다.)- 선행 달러 기호가있는
${VAR}
는 매개 변수 확장 , 가능한 추가 변환으로 변수 값으로 확장.ksh93
셸은 하위 셸을 생성하지 않는 명령 대체 형식으로${ cmd;}
도 지원합니다.
- 선행 달러 기호가있는
-
((…))
이중 괄호는 산술 명령어 를 둘러싸고 있습니다. 즉, 정수에 대한 계산입니다. 다른 프로그래밍 언어와 유사한 구문입니다.이 구문은 대부분 할당 및 조건에 사용됩니다. 일반 sh가 아닌 ksh / bash / zsh에만 있습니다.- 산술 표현식
, 표현식의 정수 값으로 확장됩니다.
- 산술 표현식
-
[ … ]
단일 괄호로 묶습니다. 조건식 . 조건식은 대부분 iv id = “303f841eb7과 같은 연산자 를 기반으로합니다. “>
는 변수가 비어 있는지 테스트하고-e "$file"
는 파일이 있는지 테스트합니다. 각 주위에 공백이 필요합니다. 연산자 (예 : 가 아닌[ "$x"="$y" ]
[ "$x" = "$y" ]
) 및 공백 또는;
대괄호 내부와 외부 모두 (예 : 가 아니라[-n "$foo"]
[ -n "$foo" ]
).
[[ … ]]
이중 괄호는 몇 가지 추가 기능이있는 ksh / bash / zsh에서 조건식의 대체 형식입니다. 예를 들어 는 파일이 일반 파일에 대한 심볼릭 링크인지 테스트하는 반면 단일 대괄호에는 [ -L "$file" ] && [ -f "$file" ]
가 필요합니다. 이 주제에 대한 자세한 내용은 따옴표없는 공백이있는 매개 변수 확장이 이중 괄호 [[에서 작동하지만 단일 괄호 [? 는 작동하지 않는 이유]를 참조하십시오. 셸에서 every 명령은 조건부 명령입니다. 모든 명령은 성공을 나타내는 0 또는 1에서 255 사이의 정수 (일부 셸에서는 더 많음)를 나타내는 반환 상태를 갖습니다. 실패. [ … ]
명령 (또는 [[ … ]]
구문 형식)은 철자가 test …
인 특정 명령입니다. div> 파일이 존재하거나 문자열이 비어 있지 않거나 숫자가 다른 숫자보다 작을 때 성공합니다. ((…))
구문 형식은 숫자가 0이 아닐 때 성공합니다. .다음은 셸 스크립트의 몇 가지 조건문 예입니다.
-
myfile
에hello
:if grep -q hello myfile; then …
-
mydir
가 디렉토리 인 경우 수행 :if cd mydir; then echo "Creating mydir/myfile" echo "some content" >myfile else echo >&2 "Fatal error. This script requires mydir to exist." fi
-
myfile
라는 파일이 있는지 테스트합니다. 현재 디렉토리 :if [ -e myfile ]; then …
-
동일하지만 매달린 기호 링크 포함 :
if [ -e myfile ] || [ -L myfile ]; then …
-
x
(숫자로 가정)의 값이 2 이상인지 테스트합니다. / p>if [ "$x" -ge 2 ]; then …
-
x
(숫자로 간주 됨)의 값이 있는지 테스트합니다. bash / ksh / zsh에서 최소 2 개 :if ((x >= 2)); then …
댓글
- 단일 괄호는
&&
-a를 지원합니다. / div>, 그래서 다음과 같이 쓸 수 있습니다 :[ -L $file -a -f $file ]
, 이는 여분의[
및…
- @AlexisWilke 연산자
-a
및-o
는 관련된 피연산자 중 일부가 연산자처럼 보이는 경우 잘못된 구문 분석으로 이어질 수 있기 때문에 문제가 있습니다. 그래서 ‘ 그것을 언급하지 않는 이유입니다. ‘ 그것들은 이점이없고 ‘ 항상 작동하지는 않습니다. 그리고 타당한 이유없이 인용되지 않은 변수 확장을 작성하지 마십시오.[[ -L $file -a -f $file ]]
는 괜찮지 만 단일 괄호를 사용하려면[ -L "$file" -a -f "$file" ]
가 필요합니다 (예 :$file
는 항상/
또는./
로 시작합니다. - 참고 ‘의
[[ -L $file && -f $file ]]
([[...]]
변형).
답변
[
대 [[
이 답변은 [
대 질문의 [[
하위 집합
Bash 4.3.11의 일부 차이점 :
-
POSIX 대 Bash 확장 프로그램 :
-
[
는 POSIX입니다. -
[[
는 Bash 확장 프로그램입니다. rom Korn 쉘
-
-
일반 명령 대 마법
-
[
이상한 이름의 일반 명령 일뿐입니다.]
는[
의 마지막 인수입니다.
Ubuntu 16.04에는 실제로 coreutils 서 제공하는
/usr/bin/[
에 실행 파일이 있습니다. / a>,하지만 bash 내장 버전이 우선합니다.Bash가 명령을 구문 분석하는 방식에 변경된 사항은 없습니다.
특히
<
는 리디렉션이고,&&
및||
는 여러 명령을 연결하고,( )
는\
로 이스케이프하지 않는 한 하위 셸이고 단어 확장은 평소처럼 발생합니다.-
[[ X ]]
는X
를 마술처럼 파싱하는 단일 구조.<
,&&
,||
및()
는 특별히 취급되며 단어 분할 규칙이 다릅니다.=
및=~
와 같은 추가 차이점도 있습니다. .
Bashese :
[
는 내장 명령이고[[
는 키워드입니다. https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword -
-
<
-
[[ a < b ]]
: 사전 식 비교 -
[ a \< b ]
: 위와 동일합니다.\
가 필요하거나 다른 명령과 마찬가지로 리디렉션을 수행합니다. Bash 확장. -
expr x"$x" \< x"$y" > /dev/null
또는[ "$(expr x"$x" \< x"$y")" = 1 ]
: POSIX 동등 항목, 참조 : https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989
-
-
&&
및||
-
[[ a = a && b = b ]]
: 참, 논리적 및 -
[ a = a && b = b ]
: 구문 오류,&&
가 AND 명령 구분자로 파싱 됨cmd1 && cmd2
-
[ a = a ] && [ b = b ]
: POSIX 신뢰할 수있는 동등 물 -
[ a = a -a b = b ]
: 거의 동일하지만, 미쳤 기 때문에 POSIX에서 사용하지 않습니다.!
또는 iv id = “와 같은a
또는b
의 일부 값에 대해 실패합니다. 논리 연산으로 해석되는 3cf953f90f “>
-
(
-
[[ (a = a || a = b) && a = b ]]
: 거짓.( )
가 없으면[[ && ]]
가[[ || ]]
-
[ ( a = a ) ]
: 구문 오류,()
는 하위 셸로 해석됩니다. -
[ \( a = a -o a = b \) -a a = b ]
: 동일하지만()
,-a
및-o
는 더 이상 사용되지 않습니다. POSIX에 의해.\( \)
가 없으면-a
가-o
-
{ [ a = a ] || [ a = b ]; } && [ a = b ]
지원 중단되지 않은 POSIX와 동일합니다. 하지만이 특별한 경우에는[ a = a ] || [ a = b ] && [ a = b ]
만 작성할 수 있습니다.||
및&&
셸 연산자는[[ || ]]
및[[ && ]]
및-o
,-a
및[
보다 우선하기 때문에 참이됩니다.
보다 우선 순위가 높기 때문에 true가됩니다.
확장시 단어 분할 및 파일 이름 생성 (split + glob )
-
x="a b"; [[ $x = "a b" ]]
: true, 따옴표 필요 없음 -
x="a b"; [ $x = "a b" ]
: 구문 오류,[ a b = "a b" ]
-
x="*"; [ $x = "a b" ]
: 현재 디렉토리에 파일이 두 개 이상있는 경우 구문 오류 . -
x="a b"; [ "$x" = "a b" ]
: POSIX 상당
로 확장 됨
=
-
[[ ab = a? ]]
: true, 패턴 일치 (* ? [
는 마법입니다). glob이 f로 확장되지 않습니다. 현재 디렉토리의 파일. -
[ ab = a? ]
:a?
glob이 확장됩니다. 따라서 현재 디렉토리의 파일에 따라 true 또는 false가 될 수 있습니다. -
[ ab = a\? ]
: false, glob 확장이 아님 -
=
및==
는[
및[[
이지만==
는 Bash 확장입니다. -
case ab in (a?) echo match; esac
: POSIX와 동일 -
[[ ab =~ "ab?" ]]
: false, Bash 3.2 이상에서""
로 마법을 잃고 bash 3.1과의 호환성을 제공하지 않습니다 (예 :BASH_COMPAT=3.1
) -
[[ ab? =~ "ab?" ]]
: 참
=~
-
[[ ab =~ ab? ]]
: 참, POSIX 확장 정규식 일치,?
가 glob 확장되지 않음 -
[ a =~ a ]
: 구문 오류. 해당하는 bash가 없습니다. -
printf "ab\n" | grep -Eq "ab?"
: POSIX에 해당 (한 줄 데이터 만 해당) -
awk "BEGIN{exit !(ARGV[1] ~ ARGV[2])}" ab "ab?"
: POSIX 상당.
권장 사항 : 항상 []
내가 본 모든 [[ ]]
구조에 대해 POSIX가 있습니다.
[[ ]]
를 사용하는 경우 :
- 이동성을 잃습니다
- 독자가 다른 bash 확장의 복잡성을 배우도록합니다.
[
는 이상한 이름의 일반 명령 일 뿐이며 특별한 의미가 없습니다.
Stéphane Chazelas (중요한 수정 및 추가)
댓글
- @St é phaneChazelas 정보 감사합니다. ‘ 답변에
expr
를 추가했습니다. 용어 ” 배쉬 예 텐션 “는 Bash가 구문을 추가 한 첫 번째 셸이라는 의미가 아닙니다. POSIX sh와 Bash를 배우는 것만으로도 이미 저를 미치게 만들었습니다. -
man test
man [
를 시도했지만 길을 잃은 경우. 그것은 POSIX 변형을 설명 할 것입니다. - 수정 :
]
는[
명령에 대한 인수이지만 ‘ t는 추가 인수가 사용되는 것을 방지합니다.]
는[
의 마지막 인수 여야하지만 테스트 표현식의 일부로 발생할 수도 있습니다. 예를 들어if [ "$foo" = ] ]; then
는 변수foo
가 “](
if [ ] = "$foo" ]; then
도 마찬가지 임). - @GordonDavisson 감사합니다. ‘ 모름, 수정되었습니다.
- @ tgm1024–Monicawasmistreat yes, 그것도 유효한 고려 사항입니다.
답변
bash 문서 :
(list)
목록은 서브 쉘 환경에서 실행됩니다 (아래 명령 실행 환경 참조). 셸의 환경에 영향을주는 변수 할당 및 내장 명령은 명령이 완료된 후에도 유효하지 않습니다. 반환 상태는 목록의 종료 상태입니다.
즉, “목록”(예 : cd
)에서 발생하는 모든 작업이 (
외부에서 영향을 미치지 않는지 확인합니다. )
. 유출되는 유일한 것은 마지막 명령의 종료 코드 또는 set -e
오류를 생성하는 첫 번째 명령 (기타 if
, while
등)
((expression))
표현식은 산술 평가에서 아래에 설명 된 규칙에 따라 평가됩니다. 표현식 값이 0이 아니면 반환 상태는 0이고, 그렇지 않으면 반환 상태입니다. 이것은 let ” expression “와 정확히 동일합니다.
수학을 할 수있는 bash 확장 프로그램입니다. 이는 expr
의 모든 제한없이 expr
를 사용하는 것과 다소 유사합니다 (예 : 모든 곳에 공백을두고 등)
[[ expression ]]
다음에 따라 0 또는 1의 상태를 반환합니다. 조건식 표현의 평가. 표현식은 조건식 아래에 설명 된 기본으로 구성됩니다. [[및]] 사이의 단어에는 단어 분할 및 경로 이름 확장이 수행되지 않습니다. 물결표 확장, 매개 변수 및 변수 확장, 산술 확장, 명령 대체, 프로세스 대체 및 따옴표 제거가 수행됩니다. -f와 같은 조건부 연산자는 기본으로 인식 되려면 인용되지 않아야합니다.[[, < 및 > 연산자는 현재 로케일을 사용하여 사전 순으로 정렬합니다.
이는
제안하지만 더 강력합니다.
[ expr ]
상태 반환 조건식 expr의 평가에 따라 0 (참) 또는 1 (거짓). 각 연산자와 연산자는 별도의 인수 여야합니다. 표현식은 조건식에서 위에서 설명한 기본으로 구성됩니다. test는 옵션을 허용하지 않으며 옵션의 끝을 나타내는-의 인수를 허용하거나 무시하지 않습니다.[…]
이것은 test
를 호출합니다. 사실 예전에는 [
가 test
에 대한 심볼릭 링크였습니다. 동일한 방식으로 작동하며 동일한 제한이 있습니다. 바이너리는 시작된 이름을 알고 있기 때문에 테스트 프로그램은 시작된시기를 [
로 알고 마지막 매개 변수 인 ]
. 재미있는 Unix 트릭.
bash
, [
및 test
는 (주석에서 언급했듯이) 내장 함수이지만 거의 동일한 제한이 적용됩니다.
주석
- 하지만
test
및[
는 물론 Bash의 내장 명령이지만 ‘ 외부 바이너리도 있습니다. -
[
의 외부 바이너리는 대부분의 최신 시스템에서test
에 대한 심볼릭 링크가 아닙니다. . - 어쨋든, 두 개의 분리 된 바이너리를 생성해야한다는 점이 흥미 롭습니다. 두 바이너리는 둘 다 결합하고 몇 개의 조건을 추가하는 대신 정확히 필요한 것을 가지고 있습니다. 실제로는
strings /usr/bin/test
에도 도움말 텍스트가 표시되어 있지만 ‘ 무슨 말을해야할지 모르겠습니다. - @ Random832 예상치 못한 arg0 동작을 피하기위한 GNU 근거에 대한 귀하의 요점을 얻었지만 POSIX 요구 사항에 대해서는 그렇게 긍정하지 않을 것입니다 ‘. 표준에 따라
test
명령은 독립 실행 형 파일 기반 명령으로 존재해야하는 것이 분명하지만,[
변형이 그렇게 구현해야합니다. 예를 들어 Solaris 11은 ‘[
실행 파일을 제공하지 않지만 그럼에도 불구하고 POSIX 표준을 완벽하게 준수합니다. - (출구 1)은 괄호 밖에서 효과가 있습니다.
답변
몇 가지 예 :
기존 테스트 :
foo="some thing" # check if value of foo is not empty if [ -n "$foo" ] ; then... if test -n "$foo" ; then...
test
및 [
는 다른 명령과 마찬가지로 명령이므로 따옴표로 묶지 않으면 변수가 단어로 분할됩니다.
새로운 스타일 테스트
[[ ... ]]
는 (최신) 특수 쉘 구조. 약간 다르게 작동합니다. 가장 분명한 것은 단어 분할 변수가 없다는 것입니다.
if [[ -n $foo ]] ; then...
산술 테스트 :
foo=12 bar=3 if (( $foo + $bar == 15 )) ; then ...
“일반 “명령 :
위의 모든 명령은 일반 명령처럼 작동하며 if
는 모든 명령을 사용할 수 있습니다.
# grep returns true if it finds something if grep pattern file ; then ...
여러 명령 :
또는 여러 명령을 사용할 수 있습니다. 명령 집합을 ( ... )
에 래핑하면 하위 셸에서 실행되어 셸 상태 (작업 디렉터리, 변수)의 임시 복사본을 만듭니다. 필요한 경우 다른 디렉토리에서 일시적으로 일부 프로그램 실행 :
# this will move to $somedir only for the duration of the subshell if ( cd $somedir ; some_test ) ; then ... # while here, the rest of the script will see the new working # directory, even after the test if cd $somedir ; some_test ; then ...
답변
그룹화 명령
Bash는 하나의 단위로 실행할 명령 목록을 그룹화하는 두 가지 방법을 제공합니다.
( list )
괄호 사이에 명령 목록을 넣으면 서브 쉘 환경이 생성되고 목록의 각 명령이 해당 서브 쉘에서 실행됩니다. 하위 셸에서 실행되는 경우 변수 할당은 하위 셸이 완료된 후에도 적용되지 않습니다.
$ a=1; (a=2; echo "inside: a=$a"); echo "outside: a=$a" inside: a=2 outside: a=1
{ list; }
중괄호 사이의 명령 목록은 현재 쉘 컨텍스트 . 서브 쉘이 작성되지 않습니다. 다음 목록은 세미콜론 (또는 개행)이 필요합니다. 출처
${} Parameter expansion Ex: ANIMAL=duck; echo One $ANIMAL, two ${ANIMAL}s $() Command substitution Ex: result=$(COMMAND) $(()) Arithmetic expansion Ex: var=$(( 20 + 5 ))
조건부 구성
단일 브래킷 즉 []
비교 용 ==, !=, <,
및 >
를 사용해야하며 숫자 비교 eq, ne,lt
및 gt
를 사용해야합니다.
향상된 대괄호 즉 [[]]
위의 모든 예에서 조건식을 묶기 위해 단일 대괄호 만 사용했지만 bash는 단일 대괄호 구문의 향상된 버전 역할을하는 이중 대괄호를 허용합니다.
비교를 위해 ==, !=, <,
및 >
는 문자 그대로 사용할 수 있습니다.
-
[
는 테스트 명령의 동의어입니다. 쉘에 내장되어 있어도 새로운 프로세스를 생성합니다. -
[[
는 프로그램이 아니라 키워드 인 새로운 개선 버전입니다. . -
[[
는Korn
및Bash
에서 이해합니다.