ksh 스크립트의 3가지 변수 중 하나에서 3개의 단어를 추출하고 싶습니다. ksh93에서 이 줄을 사용했는데 훌륭하게 작동합니다.
read A B C <<< $line
ksh88에서 위 명령을 실행할 때 다음 오류가 발생합니다.
syntax error at line ## : '<' unexpected
ksh88에서 동일한 작업을 어떻게 수행할 수 있나요?
답변1
ksh88
아니요, 여기 문자열은 및 에서 사용할 수 없습니다 pdksh
. 그러나 최신 ksh93
(원래 AT&T Korn Shell) 및 ( mksh
현재 활발히 개발 중인 pdksh
스핀오프 )에서 사용할 수 있습니다.
<<<
예 ksh93
, mksh
, GNU bash
및 zsh
.
귀하의 구체적인 질문 ...
read A B C <<< $line
...이 문제를 해결할 수 있습니다(Korn 쉘).
print -r -- $line |&
read -p A B C
이를 사용할 수도 있지만(POSIX 셸) tmpfile 성능 저하가 있습니다(반면에 <<<
있을 수도 있음).
read A B C <<EOF
$line
EOF
하지만 단어를 분리하고 싶다면 다음을 수행하세요.
set -A arrname -- $line
${arrname[0]}
그런 다음 대신 사용 $A
하고 ${arrname[1]}
교체하십시오 $B
. 단지 세 개의 요소로 분할되어도 멈추지 않는다는 점일 뿐입니다. 따라서 $line
" foo bar baz bla
" 이면 $C
"baz bla"가 포함되고 ${arrname[2]}
"baz"가 있으면 ${arrname[3]}
"bla"가 포함됩니다.
그러나 위치 매개변수가 필요하지 않은 경우 다음을 수행할 수 있습니다.
set -- $line
A=$1; shift
B=$1; shift
C=$*
그러나 단어 수가 3개 미만이면 오류가 발생합니다(확실하지 않은 경우 확인 shift
하거나 (잠재적으로 더 느린) 확인을 먼저 사용하십시오).$line
$#
[[ $line = *' '*' '[! ] ]]
이는 set … $line
와일드카드도 수행하므로(상기시켜 주신 Stéphane에게 감사드립니다) 이전에 필요합니다 set -o noglob
(일반적으로 이후에 이전 상태를 복원할 수 있습니다 set +o noglob
).
전체 공개: 저는 mksh
개발자입니다.
답변2
아니요, 여기 문자열은 zsh
1991년 2.0(및/또는 Unix 포트) 에서 가져온 것입니다 rc
. 각각의 작성자는 당시 아이디어를 교환했으며 두 사람 중 누가 아이디어를 가졌는지 또는 그의 쉘 첫 번째 중간에 포함했는지는 확실하지 않습니다.
2.05b(2002)의 bash, m+(2002)의 ksh93, R33(2008)의 mksh, 2.7(2009)의 yash에 추가되었습니다.
ksh88에는 새로운 기능이 없습니다.
여기에 있는 문서( <<
) 자체는 1970년대 후반 Bourne-shell에서 나온 것입니다.
read A B C
하나 읽어보세요논리적줄은 매우 특정한 방식으로 삽입되며 A
변수 B
( 기본값은 IFS 공백 문자 1만 포함하는 C
다소 덜 구체적 $IFS
)와 백슬래시가 이스케이프 및 줄 연속 문자 역할을 하므로 이 C
역시 매우 복잡해집니다. 없이 같은 일을 하는 것은 매우 어려울 것입니다 read
.
어쨌든 여기 <<<
와 똑같고 <<
구문만 다릅니다.
read A B C << EOF
$var
EOF
정확히 똑같다
read A B C <<< "$var" # note that some versions of bash need the quotes
모든 껍질에. 두 경우 모두, 쉘은 내용과 추가된 개행 문자를 포함하는 삭제된 임시 파일을 생성합니다(일부 쉘은 대신 파이프를 사용하지만). 그럼 read
읽어봐논리적행(백슬래시로 계속되는 여러 물리적 행에 있을 수 있음)을 입력하고 복잡한 규칙을 사용하여 변수를 채웁니다.
$var
to (SPC/TAB 구분)의 처음 3워드만 할당 하고 $A
,$B
$C
$IFS
여전히 기본값이 포함되어 있습니다.- 변수에 백슬래시와 개행 문자가 포함되어 있지 않습니다.
- 이 변수에는 3개의 단어만 포함됩니다.
처음 세 단어에 대해 다음을 수행할 수 있습니다.
function split_into {
typeset words IFS v i=0
set -o noglob
set -A words -- $1; shift
for v do
eval "$v=\${words[i]}"
((i += 1))
done
}
split_into "$var" A B C
^IFS 공백 문자, 각 POSIX는 로케일로 분류된 문자 이며 ksh88(POSIX 사양의 기반) 및 대부분의 셸에서 [:space:]
발생하는 것처럼 이는 여전히 SPC, TAB 및 NL로 제한됩니다. $IFS
이와 관련하여 제가 찾은 유일한 POSIX 호환 셸은 입니다 yash
. ksh93
( bash
5.0 기준) 다른 공백(예: CR, FF, VT...)도 포함하지만 단일 바이트 공백으로 제한됩니다(예: Solaris)(일부 영역에는 단일 바이트의 잘림 방지 공백이 포함됨)