zsh와 mksh 및 bash의 비호환성은 무엇입니까?

zsh와 mksh 및 bash의 비호환성은 무엇입니까?

다른 POSIX 호환 쉘은 bash에 대한 합리적인 대안으로 어느 정도까지 사용될 수 있습니까? 그들은 진정한 "직접" 대체물일 필요는 없지만 협력할 수 있을 만큼 충분히 가까워야 합니다.최대스크립트를 작성하고 일부 수정을 통해 나머지를 지원합니다.

  1. 최소한의 수정으로 작동하기 위해 명시적인 bash 스크립트(initscripts, DHCP 클라이언트 스크립트 등)를 원합니다.

  2. 내 자신의 좀 더 전문적인 쉘 스크립트 컬렉션이 많은 수정을 필요로 하지 않기를 바랍니다.

  3. 문자열 조작 및 기본 제공 정규식 패턴 일치와 같은 기능을 갖고 싶습니다.

내가 아는 한, 유일하게 심각한 경쟁자는 zsh와 mksh입니다. 따라서 둘 중 하나 또는 둘 모두에 능숙한 분들을 위해:

  1. zsh와 mksh에는 없지만 bash에는 어떤 기능이 있습니까?

  2. 쉘은 bash와 어떤 기능을 공유하지만 호환되지 않는 구문을 사용합니까?

답변1

스크립트 기능을 계속 사용하겠습니다. 풍부한 대화형 기능(명령줄 편집, 완성, 프롬프트 등)은 매우 다양하여 완전히 호환되지 않는 방식으로 유사한 효과를 얻는 경향이 있습니다.bash에는 없는 zsh에는 어떤 기능이 없고, 그 반대의 경우도 있습니까?일부 포인터는 대화형 사용을 위해 제공됩니다.

bash에 가장 가까운 것은ATT ksh93또는므케시(Korn 쉘 및 클론). Zsh에도 일부 기능이 있지만 zsh 기본 모드가 아닌 ksh 에뮬레이션 모드에서 실행해야 합니다.

나는 그것들을 나열하지 않을 것이다POSIX함수(모든 최신 쉘에서 사용 가능 sh) 또는 대화식 사용을 위해 위에서 언급한 상대적으로 모호한 함수도 아닙니다. 관찰은 Debian wheezy에서 발견된 bash 4.2, ksh 93u 및 mksh 40.9.20120630부터 유효합니다.

쉘 구문

인용하다

$'…'(백슬래시 보간이 포함된 리터럴 문자열) ksh93 및 mksh에서 사용할 수 있습니다. `$"..." (번역된 문자열)은 bash에만 해당됩니다.

조건부 구성

mksh 및 ksh93은 ;&명령문에서 실패해야 case하지만 ;;&후속 사례는 테스트할 수 없습니다. Mksh는 이미 ;|이 작업을 수행하고 있으며 최근 mksh에서는 ;;&호환성을 허용합니다.

((…))산술 표현식과 [[ … ]]테스트는 ksh 기능입니다. 일부 조건 연산자는 다릅니다. 아래의 "조건식"을 참조하세요.

공동 프로세스

Ksh와 bash 모두 공동 프로세스를 가지고 있지만 다르게 작동합니다.

기능

Mksh 및 ksh93은 function name {…}표준 외에도 함수 정의에 대한 구문을 지원 name () {…}하지만 functionksh에서 사용하면 범위 지정 규칙이 변경되므로 name () …호환성을 유지해야 합니다. 함수 이름에 허용되는 문자 규칙은 영숫자와 _.

지원 확장

Ksh93 및 mksh는 중괄호 확장을 지원합니다 {foo,bar}. Ksh93은 숫자 범위를 지원 {1..42}하지만 mksh는 지원하지 않습니다.

매개변수 확장

${VAR:offset}Ksh93 및 mksh는 및 하위 문자열 추출을 지원 하지만 등 ${VAR:offset:length}의 대소문자 구분은 지원하지 않습니다 ${VAR^}. 대소문자 변환을 위해 ${VAR,}bash 및 ksh에서 and를 사용할 수 있습니다 typeset -l.typeset -u

${VAR/PATTERN/STRING}를 사용하거나 교체하는 것을 지원합니다 ${VAR/PATTERN//STRING}. STRING에 대한 인용 규칙은 약간 다르므로 STRING에 백슬래시(및 다른 문자도 가능)를 사용하지 마십시오. 변수를 만들고 ${VAR/PATTERN/$REPLACEMENT}대체 항목에 인용 문자가 포함된 경우 대신 사용하십시오.

배열 확장( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]})은 ksh에서와 마찬가지로 bash에서도 동일한 방식으로 작동합니다.

${!VAR}확장되는 값(간접 변수 참조) ${OTHERVAR}은 bash에 따라 다릅니다(ksh는 다른 작업을 수행함). ksh에서 이러한 이중 확장을 얻으려면 이름 참조( )를 사용해야 합니다. 작동 원리는 동일합니다.VAROTHERVAR${!VAR}typeset -n VAR=OTHERVAR; echo "$VAR"${!PREFIX*}

프로세스 대체

ksh93은 프로세스 교체를 지원 <(…)하지만 >(…)mksh는 지원하지 않습니다.

와일드카드 패턴

shopt -s extglobbash에서 활성화가 필요한 ksh 확장 glob 모드는 ksh93 및 mksh에서 항상 사용할 수 있습니다.

Mksh는 다음과 같은 것을 지원하지 않습니다 [[:alpha:]].

IO 리디렉션

Bash와 ksh93은 의사 파일과 mksh를 정의하지만 mksh는 그렇지 않습니다./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

스크립트의 리디렉션에서 와일드카드 확장(예: 파일 이름이 패턴과 유일하게 일치하는지 여부 var="*.txt"; echo hello >$a작성 )은 bash 전용 기능입니다(다른 쉘은 스크립트에서 이 작업을 수행하지 않습니다).a.txt

<<<여기의 문자열은 bash와 마찬가지로 ksh에서도 작동합니다.

>&mksh는 구문 오류가 있는 바로가기 리디렉션도 지원하지만 ksh93은 지원하지 않습니다.

조건식

[[ … ]]이중 괄호 구문

ATT ksh93과 mksh는 모두 bash와 마찬가지로 ksh에서 이중 대괄호 구문을 지원합니다.

파일 연산자

Ksh93, mksh 및 bash는 (sticky), (egid 소유), (euid 소유), (동일 파일), (보다 최신), (보다)와 같은 더 이상 사용되지 않는 동의어를 포함하여 동일한 POSIX 확장을 지원합니다 -a.-e-k-G-O-ef-nt-ot

-N FILE(마지막 읽기 이후 수정됨) mksh에서는 지원되지 않습니다.

Mksh에는 정규식 일치 연산자가 없습니다 =~. Ksh93에는 bash와 동일한 일치를 수행하지만 일치하는 그룹을 검색하는 것과 동일한 연산자가 없습니다 BASH_REMATCH.

문자열 연산자

Ksh93 및 mksh는 bash와 동일한 문자열 비교 연산자를 지원합니다 <. Mksh는 사전순을 결정하기 위해 로케일을 사용하지 않고 문자열을 바이트 문자열로 비교합니다.>===

기타 운영자

-v VAR변수가 bash에 특정한 것으로 정의되었는지 테스트합니다. 모든 POSIX 쉘에서 [ -z "${VAR+1}" ].

내장 기능

alias

별칭에 허용되는 문자 집합은 모든 쉘에서 동일하지 않습니다. 나는 이것이 함수와 같다고 생각한다(위 참조).

builtin

Ksh93에는 라는 내장 명령이 있지만 builtin해당 이름을 내장 명령으로 실행하지는 않습니다. 별칭과 함수를 우회 하는 데 사용됩니다 . 내장 명령이 있으면 호출하고, 그렇지 않으면 외부 명령을 호출합니다 ( command이를 사용하면 피할 수 있습니다).PATH= command error_out_if_this_is_not_a_builtin

caller

이것은 bash에만 해당됩니다. ksh93에서는 를 사용하여 비슷한 효과를 얻을 수 .sh.fun있습니다 .sh.file. .sh.linenomksh가 드디어 그것을 가지게 되었습니다 LINENO.

declare,local,typeset

declareksh 의 bash별 이름입니다 typeset. 사용법 typeset: bash에서도 작동합니다.

localMksh는 의 별칭으로 정의됩니다 typeset. ksh93에서는 typeset별칭을 사용(또는 정의)해야 합니다 .

Mksh에는 연관 배열이 없습니다(미출시 버전에서는 예상됨).

typeset -tksh에는 bash(추적 기능)와 정확히 동일한 기능이 존재한다고 생각하지 않습니다.

cd

Ksh93 -e번호.

echo

Ksh93 및 mksh는 bash와 마찬가지로 -e옵션을 처리합니다. -nmksh는 또한 -Eksh93이 이를 옵션으로 처리하지 않는다는 것을 이해합니다. 백슬래시 확장은 ksh93에서는 기본적으로 꺼져 있고 mksh에서는 기본적으로 켜져 있습니다.

enable

Ksh는 내장 명령을 비활성화하는 방법을 제공하지 않습니다. 내장 명령을 사용하지 않으려면 외부 명령에 대한 경로를 찾아서 명시적으로 호출하십시오.

exec

Ksh93 예, -a하지만 아니요 -l. Mksh에는 둘 다 없습니다.

export

ksh93이나 mksh에는 이 기능이 없습니다 export -n. typeset +x foo대신 이것을 사용하면 bash와 ksh에서 작동합니다.

Ksh는 환경을 통해 기능을 내보내지 않습니다.

let

letbash와 ksh에서도 마찬가지입니다.

mapfile,readarray

이것은 bash 특정 기능입니다. while read루프나 명령 대체를 사용하여 파일을 읽고 행 배열로 분할 할 수 있습니다 . 관리 IFS및 와일드카드. 이는 다음과 같습니다 mapfile -t lines </path/to/file.

IFS=$'\n'; set -f
lines=($(</path/to/file))
unset IFS; set +f

printf

printf굉장히 유사한. ksh93은 bash의 모든 형식 지침을 지원한다고 생각합니다. mksh는 %q또는 를 지원하지 않습니다 %(DATE_FORMAT)T. 일부 설치에서는 printfmksh 내장 명령 대신 외부 명령이 호출됩니다.

printf -v VARbash에만 해당되는 ksh는 항상 표준 출력으로 인쇄합니다.

read

readline과 관련된 모든 옵션을 포함하여 여러 옵션은 bash에만 적용됩니다. 옵션 -r, -d, -n, -N는 bash, ksh93 및 mksh에서 동일 -t합니다 -u.

readonly

동일한 구문을 사용하여 Ksh93 및 mksh에서 변수를 읽기 전용으로 선언할 수 있습니다. 변수가 배열인 경우 먼저 할당한 다음 이를 사용하여 읽기 전용으로 만들어야 합니다 readonly VAR. ksh의 기능은 읽기 전용으로 만들 수 없습니다.

set,shopt

set및 의 모든 옵션은 set -oPOSIX 또는 ksh 기능입니다.

shoptbash에만 해당됩니다. 그럼에도 불구하고 많은 옵션에는 대화형 사용이 포함됩니다. 와일드카드 및 기타 기능에 대한 일부 옵션의 효과는 아래 옵션 섹션을 참조하세요.

source

.이 변종은 ksh에도 존재합니다. bash와 mksh에서는 . source다음에 현재 디렉터리를 검색하지만 PATH, ksh93에서는 ..

trap

DEBUG가짜 신호는 mksh에서 구현되지 않습니다. ksh93에서는 정보를 다르게 보고합니다. 자세한 내용은 설명서를 참조하세요.

type

ksh type에서는 whence -v. mksh에서는 type -p실행 파일의 경로를 인쇄하는 대신 사람이 읽을 수 있는 메시지가 인쇄됩니다 whence -p COMMAND.

옵션

shopt -s dotglob- 와일드카드의 도트 파일을 무시하지 마세요.

dotglobksh93의 옵션을 에뮬레이션하려면 을 설정할 수 있습니다 FIGNORE='@(.|..)'. mksh에는 그런 것이 없는 것 같습니다.

shopt -s extglob— ksh 확장 글로벌 모드

extglob옵션은 ksh에서는 항상 유효합니다.

shopt -s failglob— glob 패턴이 아무것도 일치하지 않으면 오류가 발생합니다.

나는 이것이 mksh 또는 ksh93에 존재하지 않는다고 생각합니다. zsh에서 실행됩니다( null_glob또는 설정되지 않은 경우 기본 동작).csh_null_glob

shopt -s globstar—재귀  **/적 와일드카드

Ksh93에는 **/를 통해 활성화할 수 있는 재귀적 와일드카드가 있습니다 set -G. Mksh에는 재귀적인 와일드카드가 없습니다.

shopt -s lastpipe— 상위 셸에서 파이프라인의 마지막 명령을 실행합니다.

Ksh93은 항상 상위 셸에서 파이프라인의 마지막 명령을 실행하므로 lastpipebash에서 이 옵션을 설정해야 합니다. Mksh는 항상 서브셸에서 파이프라인의 마지막 명령을 실행합니다.

shopt -s nocaseglob, shopt -s nocasematch— 대소문자를 구분하지 않는 모드

Mksh에는 대소문자를 구분하지 않는 패턴 일치 기능이 없습니다. Ksh93은 패턴별로 이를 지원합니다. 패턴 앞에 ~(i).

shopt -s nullglob— 일치하는 파일이 없는 패턴을 빈 목록으로 확장합니다.

Mksh에는 이것이 없습니다. Ksh93은 패턴별로 이를 지원합니다. 패턴 앞에 ~(N).

변하기 쉬운

분명히 대부분의 BASH_xxx변수는 ksh에 존재하지 않습니다. $BASHPID비싸지만 휴대용으로 에뮬레이트할 수 sh -c 'echo $PPID'있으며 최근 mksh에 추가되었습니다. ksh93 및 mksh에 BASH_LINE있습니다 . ksh93에 위치 ..sh.linenoLINENOBASH_SUBSHELL.sh.subshell

ENVMksh와 ksh93은 모두 시작 시 제공된 파일을 얻습니다.

EUIDUIDksh93에는 존재하지 않습니다 . Mksh USER_ID는 그들을 부르지 KSH_UID않습니다 GROUPS.

FUNCNAMEFUNCNESTksh에는 존재하지 않습니다 . Ksh93 .sh.fun.sh.level. (괄호 없이!) 로 function foo { …; }선언된 함수는 에 있습니다 $0.

GLOBIGNOREksh93에 존재하지만 이름과 구문이 다릅니다. 이라고 하며 FIGNORE콜론으로 구분된 목록이 아닌 단일 패턴입니다. 사용 @(…|…)모드. Ksh에는 FIGNOREbash가 포함되어 있지만 구문은 완전히 다릅니다.

Ksh93 및 mksh 와 같은 것은 없습니다 HOSTTYPE. 또는 .​MACHTYPEOSTYPESHELLOPTSTIMEFORMAT

Mksh에는 있지만 PIPESTATUSksh93에는 없습니다.

Mksh와 ksh93에는 RANDOM.

답변2

이 질문은 너무 광범위합니다.

둘 다므케시그리고다루기 힘든많은 쉘을 지원합니다.GNU 배쉬- 특정 확장이 있지만 항상 이해되지 않는 부분이 있습니다.

zsh는 훨씬 더 많은 것을 지원하지만 GNU bash와 같은 POSIX 셸과 호환되는 기본 zsh 모드에서만 지원됩니다.AT&T ksh93, mksh). 또한 mksh는 더 얇고 빠르며 이식성이 뛰어납니다.

일반적으로 이렇다면당신의우리는 스크립트에 대해 이야기하고 있습니다. 계속해서 테스트해 보세요. (mksh는 아직 bash4 스타일 연관 배열을 지원하지 않습니다. "declare" 명령은 bash에만 해당되며 "typeset"은 동일합니다. 저는 zsh에 대해 직접 말할 만큼 익숙하지 않습니다. ksh93에는 "local"이 없습니다. "이지만 "typeset"도 사용합니다.) 하지만 이것이 bash 없는 데비안 시스템을 실행하는 것에 관한 것이라면 잊어버리세요. bash는 "약속"(시스템의 API/ABI)의 일부로 존재하며 이에 크게 의존합니다.

면책조항: 저는 mksh 개발자입니다.

답변3

ZSH 쉘 비교

그러나 최근에는 어느 정도 확장이 교차되고 있습니다. Zsh(3.1.6 기준)에는 bash의 ${var/old/new}' feature for replacing the text old with the text new in the parameter $var. Note one difference here: while both shells implement the syntax${var/#old/new}' 및 ${var/%old/new}' for anchoring the match of old to the start or end of the parameter text, respectively, in zsh you can't put the#' 또는 {var/$old/new}'가 있습니다. 여기서 old는 문자열의 시작 부분과 일치하도록 (#s)' %' inside a parameter: in other words로 시작합니다. #' treats that as an ordinary character in zsh, unlike bash. To do this sort of thing in zsh you can use (from 3.1.7) the new syntax for anchors in any pattern,, 그리고 "(#e)"는 결말과 일치합니다. 이를 위해서는 EXTENDED_GLOB 옵션을 설정해야 합니다.

저는 mksh에 대해 잘 알지 못해서 어디서 답을 찾아야 할지 모르겠습니다.

쉘에 대한 안전한 대안을 찾고 있다면 이는 논의한 고유한 결함 측면에서 Bash와 크게 다르지 않습니다.

Perl과 같은 언어는 입력을 더 안전하게 처리합니다. 그러나 여기서도 유지 관리성이 중요합니다. Perl 쉘 대안은 잘 채택되지 않았습니다. 입력을 안전하게 처리하는 것은 쉘 관리자의 책임입니다. 그래서 스크립트를 작성할 때,모든 것을 확인하고 확인하고 확인하세요! 코드 계약을 사용하여 매번 올바른 결과를 얻으세요!

펄 쉘

쉘 쇼크에 대한 FSF 성명

답변4

함수아니요기본적으로 활성화됨mksh쉘의 역사입니다.

  • 방금 설정한 내용은 다음과 같습니다 .mkshrc.

    export HISTFILE=~/.mksh-history

관련 정보