bash (괄호, 이중 괄호, 괄호 및 이중 괄호)에서 사용될 때이 연산자가 다르게 수행하는 작업에 약간 혼란 스럽습니다.
[[ , [ , ( , ((
나는 사람들이 다음과 같은 if 문에서 그것들을 사용하는 것을 보았습니다.
if [[condition]]
if [condition]
if ((condition))
if (condition)
bash (괄호, 이중 괄호, 괄호 및 이중 괄호)에서 사용될 때이 연산자가 다르게 수행하는 작업에 약간 혼란 스럽습니다.
[[ , [ , ( , ((
나는 사람들이 다음과 같은 if 문에서 그것들을 사용하는 것을 보았습니다.
if [[condition]]
if [condition]
if ((condition))
if (condition)
답변:
if
문은 일반적으로 보이는
if commands1
then
commands2
else
commands3
fi
then
종료 코드 commands1
가 0 이면 이 절이 실행됩니다 . 종료 코드가 0이 아닌 경우 else
절이 실행됩니다. commands1
간단하거나 복잡 할 수 있습니다. 이것은, 예를 들면, 사업자 중 하나에 의해 분리 된 하나 개 이상의 파이프 라인의 순서 일 수있다 ;
, &
, &&
, 또는 ||
. if
아래 조건은 단지 특별한 경우 commands1
:
if [ condition ]
이것은 전통적인 쉘 test
명령입니다. 모든 POSIX 쉘에서 사용 가능합니다. 테스트 명령은 종료 코드를 설정하고 if
명령문이 그에 따라 작동합니다. 일반적인 테스트는 파일이 존재하는지 또는 한 숫자가 다른 숫자와 같은지 여부입니다.
if [[ condition ]]
이것은 bash 및 zsh 도 지원 하는 kshtest
에서 새롭게 업그레이드 된 변형입니다 . 이 명령은 또한 종료 코드를 설정하고 명령문이 그에 따라 작동합니다. 확장 된 기능 중에서 문자열이 정규식과 일치하는지 테스트 할 수 있습니다.test
if
if ((condition))
bash 및 zsh 도 지원 하는 또 다른 ksh 확장입니다 . 이것은 산술을 수행합니다. 산술의 결과로 종료 코드가 설정되고 명령문이 그에 따라 작동합니다. 산술 계산 결과가 0이 아닌 경우 종료 코드 0을 리턴합니다 (true). 마찬가지로이 양식은 POSIX가 아니므로 이식 할 수 없습니다.if
[[...]]
if (command)
서브 쉘에서 명령을 실행합니다. 명령이 완료되면 종료 코드를 설정하고 if
명령문이 그에 따라 작동합니다.
이와 같이 하부 쉘을 사용하는 일반적인 이유의 부작용을 제한하는 command
경우 command
변수 할당 또는 셀 환경에 다른 변화를 요구한다. 서브 쉘이 완료된 후에는 이러한 변경 사항이 유지되지 않습니다.
if command
명령이 실행되고 if
명령문은 종료 코드에 따라 작동합니다.
[
실제로 바이너리가 아닌 내부 명령 또는 상징이다. 일반적으로에 살고 있습니다 /bin
.
[
는 그대로 내장되어 test
있습니다. 호환성을 위해 사용 가능한 이진 버전이 있습니다. help [
및을 확인하십시오 help test
.
$((
즉 산술 확장이 [ $((2+2)) -eq 4 ]
(…)
괄호는 서브 쉘을 나타냅니다 . 그 안에 들어있는 것은 다른 많은 언어와 같은 표현이 아닙니다. 외부 괄호와 마찬가지로 명령 목록입니다. 이러한 명령은 별도의 하위 프로세스에서 실행되므로 괄호 안에서 수행되는 리디렉션, 할당 등은 괄호 밖에서 영향을 미치지 않습니다.
{ … }
중괄호는 명령을 그룹화한다는 점에서 괄호와 비슷하지만 그룹화가 아닌 구문 분석에만 영향을 미칩니다. 프로그램 x=2; { x=4; }; echo $x
반면 인쇄 4 x=2; (x=4); echo $x
인쇄 2. (또한있는 교정기 키워드를 구분하고 (명령 위치에서 발견 따라서 공간 후에해야 {
및 ;
전 }
. 괄호 안 반면에) 그건 그냥 구문 특질이다.)
((…))
이중 괄호 는 다른 프로그래밍 언어와 유사한 구문 으로 산술 명령어 , 즉 정수에 대한 계산을 둘러 쌉니다 . 이 구문은 대부분 할당 및 조건부에서 사용됩니다. 이것은 일반 sh가 아닌 ksh / bash / zsh에만 존재합니다.
$((…))
의 정수 값으로 확장됩니다.[ … ]
단일 괄호는 조건식을 둘러 쌉니다 . 조건식은 대부분 변수가 비어 있는지 테스트하고 파일이 존재하는지 테스트 하는 등의 연산자를 기반으로 합니다. 각 연산자 주위에 공백이 있어야하고 (예 : , not ), 괄호 안팎에 공백이나 문자가 있어야합니다 (예 : , not ).-n "$variable"
-e "$file"
[ "$x" = "$y" ]
[ "$x"="$y" ]
;
[ -n "$foo" ]
[-n "$foo"]
[[ … ]]
이중 괄호는 몇 가지 추가 기능이있는 ksh / bash / zsh의 대체 조건식입니다. 예를 들어 [[ -L $file && -f $file ]]
파일이 일반 파일에 대한 심볼릭 링크 인 반면에 단일 괄호가 필요한지 테스트하기 위해 작성할 수 있습니다 [ -L "$file" ] && [ -f "$file" ]
. 참조 따옴표없이 공백 매개 변수 확장은 대괄호 [[있지만 단일하지 괄호 [내부 작동 않는 이유는 무엇입니까? 이 주제에 대한 자세한 내용은셸에서 모든 명령은 조건부 명령입니다. 모든 명령은 성공을 나타내는 0 또는 실패를 나타내는 1에서 255 사이의 정수 (및 일부 쉘에서는 더 많은 정수)의 반환 상태를 갖습니다. [ … ]
명령 (또는 [[ … ]]
구 형태)도 철자 수 특정 커맨드 test …
및 파일이 존재하는 경우에 성공 또는 문자열은 비어 있지 않은 경우, 또는 경우에 숫자가 다른 것보다 작은 경우에는, 등 ((…))
시 구문 형태 성공 다수 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 이상 인지 테스트합니다 .
if [ "$x" -ge 2 ]; then …
x
bash / ksh / zsh에서 (숫자로 간주되는) 값이 2 이상 인지 테스트하십시오 .
if ((x >= 2)); then …
-a
대신를 &&
하나 쓸 수 있도록 : [ -L $file -a -f $file ]
여분없이 괄호 내에서 같은 수의 문자 인 [
과 ]
...
-a
및 -o
피연산자 중 일부는 사업자와 같은 모양을 포함하는 경우가 잘못된 구문 분석으로 이어질 수 있기 때문에 문제가있다. 그렇기 때문에 제가 언급하지 않은 이유는 장점이 없으며 항상 작동하지는 않습니다. 그리고 정당한 이유없이 인용되지 않은 변수 확장을 쓰지 마십시오. [[ -L $file -a -f $file ]]
괜찮지 만 단일 괄호 [ -L "$file" -a -f "$file" ]
(예 : $file
항상 /
또는로 시작하는 경우 ./
)가 필요합니다.
[[ -L $file && -f $file ]]
(더 -a
로 [[...]]
변형).
로부터 bash는 문서 :
(list)
리스트는 서브 쉘 환경에서 실행됩니다 (아래 명령 실행 환경 참조). 쉘 환경에 영향을주는 변수 할당 및 내장 명령은 명령이 완료된 후에도 유효하지 않습니다. 반환 상태는 list의 종료 상태입니다.
다시 말해, 'list'에서 발생하는 모든 일 (예 : a cd
)이 (
and 외부에 영향을 미치지 않는지 확인하십시오 )
. 누출있는 유일한 방법은 마지막 명령 또는 함께 종료 코드입니다 set -e
(A와 같은 몇 가지 이외의 오류가 발생 첫 번째 명령 if
, while
등)
((expression))
이 표현은 아래의 산술 평가에 설명 된 규칙에 따라 평가됩니다. 표현식의 값이 0이 아닌 경우 리턴 상태는 0입니다. 그렇지 않으면 리턴 상태는 1입니다. 이것은 "표현식"과 정확히 같습니다.
이것은 수학을 할 수있는 bash 확장입니다. 이것은 expr
모든 제한 사항없이 사용하는 것과 다소 비슷합니다 expr
(예 : 어디에나 공간이 있거나 탈출하는 *
등).
[[ expression ]]
조건식 표현식의 평가에 따라 0 또는 1의 상태를 리턴하십시오. 식은 조건식에서 아래에 설명 된 기본으로 구성됩니다. [[와]] 사이의 단어에 대해서는 단어 분할 및 경로 이름 확장이 수행되지 않습니다. 물결표 확장, 매개 변수 및 변수 확장, 산술 확장, 명령 대체, 프로세스 대체 및 따옴표 제거가 수행됩니다. -f와 같은 조건 연산자는 따옴표로 묶어 인용 부호로 인식해야합니다.[[와 함께 사용하면 <및> 연산자는 현재 로케일을 사용하여 사전 식으로 정렬합니다.
이 기능은 문자열, 숫자 및 파일을 test
오퍼와 비슷하지만 더 강력 하게 비교하는 고급 테스트를 제공합니다.
[ expr ]
조건식 expr의 평가에 따라 0 (true) 또는 1 (false)의 상태를 반환합니다. 각 연산자와 연산자는 별도의 인수 여야합니다. 표현식은 위에서 언급 한 조건식 아래에 설명 된 기본으로 구성됩니다. 테스트는 옵션을 허용하지 않으며 옵션의 끝을 나타내는 인수를 무시하거나 무시하지 않습니다.[...]
이것을 호출합니다 test
. 사실, 옛날 [
에는와의 상징적 링크였습니다 test
. 동일한 방식으로 작동하며 동일한 제한이 있습니다. 바이너리는 그것이 시작된 이름을 알고 있기 때문에 테스트 프로그램은 매개 변수를 찾을 때까지 매개 변수를 구문 분석 할 수 있습니다 ]
. 재미있는 유닉스 트릭.
의 경우에는 그 주 bash
, [
및 test
내장 함수 (코멘트에서 언급 한 바와 같이)이다, 그러나 거의 같은 제한 사항이 적용됩니다.
test
과는 [
물론 배쉬 내장 명령입니다,하지만 외부 바이너리도 존재 가능성이 높습니다.
[
는 test
대부분의 최신 시스템에서 심볼릭 링크가 아닙니다 .
strings /usr/bin/test
도움말 텍스트가 있음을 보여 주지만 무엇을 말 해야할지 모르겠습니다.
test
명령은 표준에 의해 독립형 파일 기반 명령으로 존재해야 하지만 분명히 그 [
변형을 구현할 필요는 없다. 예를 들어, Solaris 11은 [
실행 파일을 제공하지 않지만 POSIX 표준을 완벽하게 준수합니다
[
vs [[
이 답변은 질문 의 [
vs [[
하위 집합을 다룹니다.
Bash 4.3.11과의 차이점 :
POSIX vs Bash 확장 :
[
POSIX입니다[[
https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs에 설명 된 Bash 확장 프로그램 ¹입니다.정규 명령 대 마법
[
이상한 이름을 가진 일반적인 명령입니다.
]
[
추가 인수가 사용되지 않도록 하는 인수입니다 .
우분투 16.04는 실제로 /usr/bin/[
coreutils 가 제공 하는 실행 파일을 가지고 있지만 bash 내장 버전이 우선합니다.
Bash가 명령을 구문 분석하는 방식에는 아무런 변화가 없습니다.
특히, <
리디렉션입니다, &&
그리고 ||
여러 명령을 연결, ( )
하지 않는 한에서 탈출 서브 쉘을 생성 \
하고, 단어 확장은 평소와 같이 발생합니다.
[[ X ]]
X
마술처럼 파싱 하는 단일 구문입니다. <
, &&
, ||
및 ()
특수 처리, 워드 분할 규칙이 다릅니다된다.
같은 더 차이도있다 =
하고 =~
.
Bashese에서 : [
내장 명령이며 [[
키워드입니다 : https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: 사전 비교[ a \< b ]
: 같은 상기와. \
다른 명령과 마찬가지로 필요하거나 리디렉션합니다. 배쉬 확장.expr a \< b > /dev/null
: 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 -a b = b ]
: POSIX³에서는 동일하지만 더 이상 사용되지 않습니다.[ a = a ] && [ b = b ]
: POSIX 및 신뢰할 수있는 제품(
[[ (a = a || a = b) && a = b ]]
: 거짓[ ( a = a ) ]
: 구문 오류, ()
서브 쉘로 해석[ \( a = a -o a = b \) -a a = b ]
: 동등하지만 ()
POSIX에서 사용되지 않습니다.{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX 상당 5확장시 단어 분리 및 파일 이름 생성 (분할 + 글로브)
x='a b'; [[ $x = 'a b' ]]
: 따옴표가 필요하지 않습니다.x='a b'; [ $x = 'a b' ]
: 구문 오류, 확장 [ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: 현재 디렉토리에 둘 이상의 파일이 있으면 구문 오류가 발생합니다.x='a b'; [ "$x" = 'a b' ]
: POSIX 상당=
[[ ab = a? ]]
: 패턴 일치를 수행하기 때문에 true입니다 ( * ? [
매직). 현재 디렉토리의 파일로 확장하지 않습니다.[ ab = a? ]
: a?
글로브가 확장됩니다. 따라서 현재 디렉토리의 파일에 따라 true 또는 false 일 수 있습니다.[ ab = a\? ]
: false, glob 확장이 아님=
와 ==
모두 동일 [
하고 [[
있지만, ==
배쉬 확장입니다.case ab in (a?) echo match; esac
: POSIX 상당[[ ab =~ 'ab?' ]]
: 거짓 4 , 마법을 잃는다''
[[ ab? =~ 'ab?' ]]
: 사실=~
[[ ab =~ ab? ]]
: true, POSIX 확장 정규식 일치, ?
확장하지 않음[ a =~ a ]
: 구문 오류. bash와 동등한 것은 없습니다.printf 'ab\n' | grep -Eq 'ab?'
: POSIX 동등 (단일 데이터 만)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: POSIX 상당.권장 사항 : 항상 사용하십시오 []
.
[[ ]]
내가 본 모든 구성에 대해 POSIX 등가물 이 있습니다.
당신이 당신을 사용하는 경우 [[ ]]
:
[
이상한 의미를 가진 일반적인 명령이며 특별한 의미가 없습니다.¹ [[...]]
Korn 쉘 의 동등한 구성에서 영감을 받음
² 그러나 a
또는 b
(와 같은 +
또는 index
) 의 일부 값에는 실패하고 10 진수 정수 a
와 같으면 숫자 비교를 수행합니다 b
. expr "x$a" '<' "x$b"
둘 다 해결합니다.
³도의 일부 값 실패 a
나 b
같은 !
나 (
.
4 떠들썩한 파티 3.2 이상 및 3.1 날리고 제공 호환성 (와 같이 사용할 수 없습니다 BASH_COMPAT=3.1
)
5 및 쉘 연산자 ( 및 연산자 또는 / 연산자 와 반대 )가 동일한 우선 순위를 갖기 때문에 그룹화 (여기서 {...;}
명령 그룹을 사용 (...)
하여 불필요한 서브 쉘을 실행 함)는 필요하지 않습니다 . 따라서 동일합니다.||
&&
||
&&
[[...]]
-o
-a
[
[ a = a ] || [ a = b ] && [ a = b ]
expr
답변에 추가 했습니다. "Bash extension"이라는 용어는 Bash가 구문을 추가 한 최초의 쉘이라는 것을 의미하지는 않습니다. POSIX sh vs Bash를 배우는 것은 이미 나를 미치게하기에 충분합니다.
man test
당신이 시도 man [
하고 길을 잃었 는지 확인 하십시오 . POSIX 변형에 대해 설명하겠습니다.
몇 가지 예 :
전통적인 시험 :
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
.