기본적으로 이식성 (및 안정성) 문제입니다.
처음에는 echo
옵션을 수락하지 않았으며 아무것도 확장하지 않았습니다. 공백 문자로 구분되고 개행 문자로 종료되는 인수를 출력하는 것이 전부였습니다.
이제 누군가 줄 echo "\n\t"
바꿈 또는 탭 문자를 출력하거나 후행 줄 바꿈 문자를 출력하지 않는 옵션을 사용할 수 있다면 좋을 것이라고 생각했습니다 .
그런 다음 더 열심히 생각했지만 셸에 해당 기능을 추가하는 대신 ( perl
큰 따옴표 안에 \t
실제로 탭 문자가있는 것처럼)을 추가했습니다 echo
.
데이빗 콘은 실수를 깨닫고 쉘 따옴표 새로운 형태의 도입 : $'...'
나중에에 의해 복사 된 bash
과를 zsh
하지만 너무 늦은 시간에 의해했다.
표준 UNIX 지금 때 echo
두 개의 문자가 포함 된 인수 수신 \
하고 t
대신 그들을 출력을, 그것은 탭 문자를 출력합니다. 그리고 \c
인수에서 보자 마자 출력을 중지합니다 (따라서 후행 줄 바꿈도 출력되지 않습니다).
다른 쉘 / 유닉스 벤더 / 버전에서는 다르게 선택했습니다 : -e
이스케이프 시퀀스를 확장하는 -n
옵션 과 후행 줄 바꿈을 출력하지 않는 옵션을 추가했습니다 . 일부는 가지고 -E
일부가, 이스케이프 시퀀스를 비활성화 할 -n
수 있지만 -e
, 하나에 의해 지원되는 이스케이프 시퀀스 목록 echo
구현은 다른 지원으로 반드시 동일하지 않습니다.
Sven Mascheck에는 문제의 범위를 보여주는 멋진 페이지가 있습니다 .
이들에 echo
옵션을 지원 구현하는 어떠한 지원 일반적으로 없다 --
종료 옵션을 표시하는합니다 ( echo
할 일부 비 본쉘의 내장, 그리고 zsh을 지원 -
하는 생각에 대한) 예를 들어, 그래서 그것을 출력 어려운, "-n"
과 echo
에 많은 껍질.
같은 몇 가지 껍질에 bash
¹ 또는 ksh93
² 또는 yash
( $ECHO_STYLE
변수), 동작도 GNU 방법 쉘이 컴파일 또는 환경 (에 따라 echo
'경우의 동작도 변경됩니다 $POSIXLY_CORRECT
환경과 버전 함께 4 , zsh
의 그것과 bsd_echo
옵션, 일부 pdksh 기반 posix
옵션 또는 호출 여부 sh
). 따라서 bash
echo
동일한 버전의 두 개가 동일한 bash
동작을 보장하지는 않습니다.
POSIX의 말 : 첫 번째 인수 -n
이거나 임의의 인수에 백 슬래시가 포함되어 있으면 동작이 지정되지 않은 것 입니다. bash
그 점에서 echo는 POSIX echo -e
가 아닙니다. 예를 들어 -e<newline>
POSIX가 요구 하는 대로 출력되지 않습니다 . UNIX 스펙은 더 엄격 -n
하므로 \c
출력을 중지하기 위해 이스케이프 시퀀스를 포함하여 일부 이스케이프 시퀀스의 확장을 금지 하고 필요로합니다 .
많은 구현이 호환되지 않는 경우 이러한 사양은 실제로 구출되지 않습니다. macOS 5 와 같은 일부 인증 된 시스템도 호환되지 않습니다.
현재 현실을 실제로 나타내려면 POSIX는 실제로 다음과 같이 말해야합니다 . 첫 번째 인수가 ^-([eEn]*|-help|-version)$
확장 정규 표현식 과 일치 하거나 인수에 백 슬래시 (또는 α
BIG5 문자 세트를 사용하는 로케일 과 같은 백 슬래시 문자 인코딩이 포함 된 문자)가 포함 된 경우 동작은 다음과 같습니다. 불특정.
대체로 백 슬래시 문자를 포함하지 않고로 시작하지 echo "$var"
않는지 확인하지 않으면 어떤 결과 가 출력되는지 알 $var
수 없습니다 -
. POSIX 사양은 실제로 printf
그 경우 대신 사용하도록 지시합니다 .
따라서 echo
제어 할 수없는 데이터를 표시 하는 데 사용할 수 없습니다 . 즉, 스크립트를 작성 중이고 외부 입력 (사용자의 인수 또는 파일 시스템의 파일 이름 등)을 사용 echo
하는 경우 이를 표시하는 데 사용할 수 없습니다 .
괜찮습니다 :
echo >&2 Invalid file.
이것은 아니다:
echo >&2 "Invalid file: $file"
( 컴파일 타임이나 환경을 통해 옵션이 활성화되지 않은 경우 echo
와 같은 일부 (UNIX 호환이 아닌) 구현 에서는 정상적으로 작동하지만).bash
xpg_echo
file=$(echo "$var" | tr ' ' _)
대부분의 구현에서 확인되지 않은 경우 (예외적 인 yash
로 ECHO_STYLE=raw
(주의 할 점으로 yash
의 변수가 임의의 바이트 시퀀스 그렇게하지 임의의 파일 이름)를 길게 할 수 zsh
S ' echo -E - "$var"
6 ).
printf
반면,의 기본 사용법으로 제한되는 경우 더 안정적입니다 echo
.
printf '%s\n' "$var"
$var
포함 할 수있는 문자에 상관없이 개행 문자 뒤에 내용을 출력 합니다.
printf '%s' "$var"
후행 줄 바꿈 문자없이 출력합니다.
이제는 printf
구현 간에 차이가 있습니다. POSIX에서 지정한 핵심 기능이 있지만 확장 기능이 많이 있습니다. 예를 들어, 일부 %q
는 인수를 인용하기 위해 a 를 지원 하지만 어떻게 수행되는지는 쉘마다 다르며 일부 \uxxxx
는 유니 코드 문자를 지원 합니다. 동작 printf '%10s\n' "$var"
은 멀티 바이트 로케일에 따라 다르며 최소한 세 가지 다른 결과가 있습니다.printf %b '\123'
그러나 결국 POSIX 기능 세트를 고수 printf
하고 너무 멋진 것을 시도하지 않으면 문제가 없습니다.
그러나 첫 번째 인수는 형식이므로 변수 / 제어되지 않은 데이터를 포함해서는 안됩니다.
다음을 echo
사용하여 보다 안정적인 것을 구현할 수 있습니다 printf
.
echo() ( # subshell for local scope for $IFS
IFS=" " # needed for "$*"
printf '%s\n' "$*"
)
echo_n() (
IFS=" "
printf %s "$*"
)
echo_e() (
IFS=" "
printf '%b\n' "$*"
)
local IFS
많은 쉘을 사용하거나 다음과 같이 작성하면 서브 쉘 (대부분의 쉘 구현에서 추가 프로세스를 생성 함을 의미 함)을 피할 수 있습니다 .
echo() {
if [ "$#" -gt 0 ]; then
printf %s "$1"
shift
fi
if [ "$#" -gt 0 ]; then
printf ' %s' "$@"
fi
printf '\n'
}
노트
1. 방법 bash
의 echo
변경 될 수 있습니다 행동.
으로 bash
, 실행시의 동작을 제어하는 두 가지가 있습니다 echo
(옆 enable -n echo
또는 재정의 echo
기능 또는 별칭으로)를 다음 xpg_echo
bash
옵션을 여부는 bash
POSIX 모드에 있습니다. posix
모드 bash
가로 호출 sh
되거나 POSIXLY_CORRECT
환경에 있거나 posix
옵션을 사용하는 경우 활성화 할 수 있습니다 .
대부분의 시스템에서 기본 동작 :
$ bash -c 'echo -n "\0101"'
\0101% # the % here denotes the absence of newline character
xpg_echo
UNIX가 요구하는 순서를 확장합니다 :
$ BASHOPTS=xpg_echo bash -c 'echo "\0101"'
A
여전히 명예 -n
와 -e
(그리고 -E
) :
$ BASHOPTS=xpg_echo bash -c 'echo -n "\0101"'
A%
와 xpg_echo
POSIX 모드 :
$ env BASHOPTS=xpg_echo POSIXLY_CORRECT=1 bash -c 'echo -n "\0101"'
-n A
$ env BASHOPTS=xpg_echo sh -c 'echo -n "\0101"' # (where sh is a symlink to bash)
-n A
$ env BASHOPTS=xpg_echo SHELLOPTS=posix bash -c 'echo -n "\0101"'
-n A
이번에 bash
는 POSIX와 UNIX를 모두 준수합니다. POSIX 모드에서는 다음 bash
과 같이 출력되지 않으므로 여전히 POSIX 호환이 아닙니다 -e
.
$ env SHELLOPTS=posix bash -c 'echo -e'
$
xpg_echo 및 posix의 기본값은 컴파일시 --enable-xpg-echo-default
및 --enable-strict-posix-default
옵션을 configure
스크립트로 사용하여 정의 할 수 있습니다 . 그것은 일반적으로 최신 버전의 OS / X가 빌드하기 위해 수행하는 작업 /bin/sh
입니다. 올바른 마음으로 유닉스 / 리눅스 구현 / 배포는 일반적으로 그렇게하지 /bin/bash
않습니다 . 사실, 사실은 아닙니다. /bin/bash
Oracle이 Solaris 11 (선택적 패키지)과 함께 제공 --enable-xpg-echo-default
되는 것은 Solaris 10의 경우와 달리 내장 된 것 같습니다 .
2. 방법 ksh93
의 echo
동작을 변경할 수 있습니다.
에서 이스케이프 시퀀스를 확장하고 옵션을 인식 ksh93
하는지 여부는 환경 변수 및 / 또는 환경 변수 echo
의 내용에 따라 다릅니다 .$PATH
$_AST_FEATURES
경우는 $PATH
포함 된 구성 요소 포함 /5bin
또는 /xpg
전과 /bin
또는 /usr/bin
다음은 시스템 V / UNIX의 방식으로 작동 구성 요소 (시퀀스를 확장, 옵션을 적용하지 않습니다). 찾 /ucb
거나 /bsd
먼저 또는 $_AST_FEATURES
7에 포함되어 있으면 UNIVERSE = ucb
BSD 3 방식으로 작동합니다 ( -e
확장 가능, 인식 -n
).
기본값은 시스템에 따라 다릅니다 (데비안의 BSD) ( builtin getconf; getconf UNIVERSE
최신 버전 ksh93 의 출력 참조 ).
$ ksh93 -c 'echo -n' # default -> BSD (on Debian)
$ PATH=/foo/xpgbar:$PATH ksh93 -c 'echo -n' # /xpg before /bin or /usr/bin -> XPG
-n
$ PATH=/5binary:$PATH ksh93 -c 'echo -n' # /5bin before /bin or /usr/bin -> XPG
-n
$ PATH=/5binary:$PATH _AST_FEATURES='UNIVERSE = ucb' ksh93 -c 'echo -n' # -> BSD
$ PATH=/ucb:/foo/xpgbar:$PATH ksh93 -c 'echo -n' # /ucb first -> BSD
$ PATH=/bin:/foo/xpgbar:$PATH ksh93 -c 'echo -n' # /bin before /xpg -> default -> BSD
3. echo -e를위한 BSD?
-e
옵션 처리를위한 BSD에 대한 언급 은 약간 오해의 소지가 있습니다. 서로 다르고 호환되지 않는 echo
행동의 대부분은 AT & T에서 소개되었습니다.
\n
, \0ooo
, \c
프로그래머의 워크 벤치 (유닉스 V6 기준) UNIX, 나머지 (에서 \b
, \r
유닉스 시스템 III에서 ...) 참조 .
-n
유닉스 V7에서 (Dennis Ritchie Ref가 작성 )
-e
유닉스 V8에서 (Dennis Ritchie Ref가 작성 )
-E
자체는 아마도 처음 온 bash
(에 CWRU / CWRU.chlog 1.13.5 버전 , 브라이언 폭스 1992년 10월 18일에 추가 언급 GNU의 echo
십일 이후 출시 된 SH-utils를 1.8에서 조금 후에 복사를)
그동안 echo
의 내장 sh
또는 BSD의 지원했다 -e
가 90 년대 초에 대한 Almquist 쉘을 사용하기 시작한 날 이후, 독립 echo
이 날 유틸리티 (거기를 지원하지 않습니다 FreeBSD는echo
아직 지원하지 않습니다 -e
는 지원을하지 불구하고, -n
같은 유닉스 V7 (그리고 \c
마지막 인수의 끝에서만).
의 처리 -e
에 추가 ksh93
의 echo
BSD의에 때 우주 와 2006 년에 발표 된 ksh93r 버전에서 컴파일시에 해제 할 수 있습니다.
8.31의 GNU 에코 동작 변경
로 coreutils 8.31 (이후 이 커밋 ), GNU는 echo
지금 POSIXLY_CORRECT 환경에있을 때의 동작과 일치하도록 기본적으로 이스케이프 시퀀스 확장 bash -o posix -O xpg_echo
의의 echo
(참조 내장을 버그 리포트를 ).
5. macOS echo
대부분의 macOS 버전은 OpenGroup으로부터 UNIX 인증을 받았습니다 .
그들의 sh
내장은 echo
그것의로 준수 bash
와 내장 (아주 오래된 버전) xpg_echo
기본적으로 사용할 수는 있지만, 자신의 독립 실행 형 echo
유틸리티가 없습니다. env echo -n
대신에 출력하는 것도 -n<newline>
, env echo '\n'
출력하지 \n<newline>
대신 <newline><newline>
.
이것은 /bin/echo
FreeBSD의 첫 번째 인수 인 경우 첫 번째 인수 인 경우 줄 바꿈 출력을 억제 -n
하고 마지막 인수가 끝나는 경우 (1995 년 이후) 줄 바꿈 출력을 억제 \c
하지만 UNIX에서 필요로하는 다른 백 슬래시 시퀀스는 지원하지 않습니다 \\
.
6. echo
임의의 데이터를 그대로 출력 할 수있는 구현
엄밀히 말하면, 당신은 또한 FreeBSD의 / 맥 OS 것을 셀 수 말하기 /bin/echo
(안 자신의 쉘 위의 echo
내장은) 여기서 zsh
의 echo -E - "$var"
또는 yash
의가 ECHO_STYLE=raw echo "$var"
( printf '%s\n' "$var"
) 작성할 수 있습니다 :
/bin/echo "$var
\c"
지원 구현 -E
및 -n
(또는로 구성 할 수 있습니다)도 수행 할 수 있습니다
echo -nE "$var
"
그리고 zsh
's이 (가) echo -nE - "$var"
( printf %s "$var"
) 기록 될 수있다
/bin/echo "$var\c"
7. _AST_FEATURES
그리고 ASTUNIVERSE
가 _AST_FEATURES
직접 조작하는 것은 아닙니다, 명령 실행을 통해 AST 구성 설정을 전파하는 데 사용됩니다. 구성은 문서화되지 않은 astgetconf()
API 를 통해 수행되어야합니다 . 내부 ksh93
에서 getconf
내장 (을 사용 builtin getconf
하거나 호출 하여 사용 가능 command /opt/ast/bin/getconf
)은astgetconf()
예를 들어 설정을 ( SysV 방식으로 작동 builtin getconf; getconf UNIVERSE = att
하도록) 변경해야 UNIVERSE
합니다 . 그 후에 환경 변수에 포함되어 있음을 알 수 있습니다 .att
echo
$_AST_FEATURES
UNIVERSE = att
echo -e
?