동료는 최근 코드 검토 에서 구조가 다음과 같은 구조 [[ ]]
보다 선호되어야 한다고 주장했습니다.[ ]
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
그는 근거를 제시 할 수 없었다. 하나 있습니까?
동료는 최근 코드 검토 에서 구조가 다음과 같은 구조 [[ ]]
보다 선호되어야 한다고 주장했습니다.[ ]
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
그는 근거를 제시 할 수 없었다. 하나 있습니까?
답변:
[[
놀라움이 적고 일반적으로 사용하는 것이 더 안전합니다. 그러나 이식성이 없습니다-POSIX는 수행하는 작업을 지정하지 않으며 일부 쉘 만 지원합니다 (bash 외에도 ksh도 지원한다고 들었습니다). 예를 들어, 할 수 있습니다
[[ -e $b ]]
파일이 있는지 테스트합니다. 그러나에 [
, 당신은 인용이 $b
는 인수를 분할하고 같은 일을 확장하기 때문에, "a*"
(여기서 [[
문자 그대로 소요). 그것은 또한 [
외부 프로그램이 될 수있는 방법 과 관련이 있으며 다른 모든 프로그램과 마찬가지로 정상적으로 인수를 수신합니다 (내장 프로그램 일 수도 있지만 여전히이 특별한 처리 기능은 없습니다).
[[
=~
C와 같은 언어로 알려진 연산자 와 함께 정규 표현식 일치와 같은 다른 멋진 기능 도 있습니다. 여기에 좋은 페이지가 있습니다 : 테스트 [
와 의 차이점은 무엇입니까 [[
? 및 배쉬 테스트
[[ ]]
동일한 의미로 해석됩니다 [ ]
.
#!/bin/sh
하지만 #!/bin/bash
BASH 특정 기능에 의존하자마자 Bourne 쉘이 더 이상 이식 가능하지 않다는 것을 나타내도록 스크립트 를 전환합니다 .
행동 차이
Bash 4.3.11과의 차이점 :
POSIX vs Bash 확장 :
[
POSIX입니다[[
Bash 확장입니다 ¹정규 명령 대 마법
[
이상한 이름을 가진 일반적인 명령입니다.
]
[
추가 인수가 사용되지 않도록 하는 인수입니다 .
우분투 16.04는 실제로 coreutils 가 /usr/bin/[
제공 하는 실행 파일을 가지고 있지만 bash 내장 버전이 우선합니다.
Bash가 명령을 구문 분석하는 방식에는 아무런 변화가 없습니다.
특히, <
리디렉션,이다 &&
와 ||
, CONCATENATE 여러 명령 ( )
에 의해 탈출하지 않는 한 서브 쉘을 생성 \
하고, 단어 확장은 평소와 같이 발생합니다.
[[ X ]]
X
마술처럼 파싱 하는 단일 구문입니다. <
, &&
, ||
및 ()
특수 처리, 워드 분할 규칙이 다릅니다된다.
같은 더 차이도있다 =
하고 =~
.
Bashese에서 : [
내장 명령이며 [[
키워드입니다 : /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: 사전 비교[ a \< b ]
: 같은 상기와. \
다른 명령과 마찬가지로 필요하거나 리디렉션합니다. 배쉬 확장.expr a \< b > /dev/null
: POSIX와 동등한 ², 다음을 참조하십시오 : Bash에서 사전 식 이하의 문자열을 테스트하는 방법은 무엇입니까?&&
과 ||
[[ 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 상당확장시 단어 분리 및 파일 이름 생성 (분할 + 글로브)
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?' ]]
: 거짓 ⁴, 마법을 잃는다 ''
[[ ab? =~ 'ab?' ]]
: 진실=~
[[ ab =~ ab? ]]
: 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
같은 !
나 (
.
⁴ 떠들썩한 파티 3.2 이상 3.1 배시에 제공 상용 성 (와 같이 사용할 수 없습니다 BASH_COMPAT=3.1
)
shell 및 쉘 연산자 ( 및 연산자 또는 / 연산자 와 반대 )가 동일한 우선 순위를 갖기 때문에 그룹화 (여기서 {...;}
명령 그룹을 사용 (...)
하여 불필요한 서브 쉘을 실행 함)는 필요하지 않습니다 . 따라서 동일합니다.||
&&
||
&&
[[...]]
-o
-a
[
[ a = a ] || [ a = b ] && [ a = b ]
[
같은 이유로 사용 합니다.
[[ ]]
더 많은 기능이 있습니다. 자세한 내용은 Advanced Bash 스크립팅 안내서 를 참조하십시오. 특히 7 장의 확장 테스트 명령 섹션을 참조하십시오 .
또한, 가이드 노트로서 [[ ]]
ksh88 (1988 년 Korn 쉘)에 도입되었습니다.
에서 어떤 비교, 테스트, 브래킷 또는 이중 브라켓, 빠른입니까? ( http://bashcurescancer.com )
이중 괄호는“복합 명령”으로, 테스트와 단일 괄호는 쉘 내장입니다 (실제로 같은 명령). 따라서 단일 괄호와 이중 괄호는 다른 코드를 실행합니다.
테스트 및 단일 브래킷은 별도의 외부 명령으로 존재하므로 가장 이식성이 뛰어납니다. 그러나 원격으로 최신 버전의 BASH를 사용하는 경우 이중 괄호가 지원됩니다.
[[
이 가져올 수있는 것에 대해서는 신경 쓰지 않았습니다 . 그러나 나는 구식 구식 방귀입니다 :-)
[
하고 test
심지어 외부 버전도 존재하지만.
PS1=...crazy stuff...
및 / 또는 $PROMPT_COMMAND
); 이를 위해 스크립트 실행이 지연 되는 것을 원하지 않습니다 .
apt-get update
마지막으로 실행 된 후 X 시간 이상 지난 경우에는 실행해야 합니다. 이미 너무 긴 코드 제약 목록에서 이식성을 유지할 수있는 경우 큰 도움이됩니다.
Google 스타일 가이드 를 따르는 경우 :
테스트 [
및[[
[[ ... ]]
아니오 경로 이름 확장으로 에러를 감소 시키거나 단어 분할 사이에 발생[[
하고]]
, 그리고[[ ... ]]
정규 표현 매칭을 허용[ ... ]
하지 않는다.
# This ensures the string on the left is made up of characters in the
# alnum character class followed by the string name.
# Note that the RHS should not be quoted here.
# For the gory details, see
# E14 at https://tiswww.case.edu/php/chet/bash/FAQ
if [[ "filename" =~ ^[[:alnum:]]+name ]]; then
echo "Match"
fi
# This matches the exact pattern "f*" (Does not match in this case)
if [[ "filename" == "f*" ]]; then
echo "Match"
fi
# This gives a "too many arguments" error as f* is expanded to the
# contents of the current directory
if [ "filename" == f* ]; then
echo "Match"
fi
[[ -d ~ ]]
true를 반환합니다 ( ~
로 확장 됨을 의미 함 /home/user
). 나는 구글의 글이 더 정확해야한다고 생각한다.
[[]] 이중 괄호는 특정 버전의 SunOS에서 지원되지 않으며 다음과 같이 함수 선언 내부에서 완전히 지원되지 않습니다. GNU bash, 버전 2.02.0 (1) -release (sparc-sun-solaris2.6)
간단히 말해서, [[다른 프로세스를 포크하지 않기 때문에 더 좋습니다. 다른 프로세스를 분기하기 때문에 대괄호 나 단일 대괄호는 이중 대괄호보다 느립니다.
type [
이것을 사용하여보십시오 .
[[
,와 구별되는 바와 같이 [
bash 명령 줄 인터프리터가 구문을 해석합니다. bash에서을 입력하십시오 type [[
. unix4linux는 고전적인 Bourne-shell [
테스트에서 진리 값을 결정하기 위해 새로운 프로세스를 분기 했지만 [[
구문 (ksh에서 bash, zsh 등으로 차용)은 그렇지 않습니다.
[
Bash뿐만 아니라 Dash ( /bin/sh
모든 Debian 파생 Linux 배포판)에 내장되어 있습니다.
[[
코드가 좋은 분명하다 그것으로,하지만 그 날을 기억 할 때 포트거야 아닌 기본 쉘 시스템에서 귀하의 scriptworksbash
또는ksh
, 등[
은 추악하고 성가 시지만AK-47
어떤 상황에서도 작동 합니다.