/ bin / sh의 콜론에서 문자열 분리


9

dash스크립트는 다음과 같은 형식의 매개 변수를 사용합니다 hostname:port.

myhost:1234

포트는 선택적인 반면,

myhost

호스트와 포트를 별도의 변수로 읽어야합니다. 첫 번째 경우에는 다음을 수행 할 수 있습니다.

HOST=${1%%:*}
PORT=${1##*:}

그러나 포트가 생략 된 두 번째 경우에는 작동하지 않습니다. echo ${1##*:}빈 문자열 대신 호스트 이름을 반환합니다.

Bash에서 나는 할 수 있었다 :

IFS=: read A B <<< asdf:111

그러나 그것은 작동하지 않습니다 dash.

나는에 문자열을 분할 할 수 있습니다 :외부 프로그램을 (호출하지 않고, 대시 awk, tr등)?


4
IPv6를 지원하려면 마지막 콜론으로 분할하고 대괄호 안에 콜론으로 분할하지 마십시오
Ferrybig

@Ferrybig %%은 욕심이 많기 때문에 ()와는 달리 %실제로는 적어도 부분적으로이 작업을 수행합니다. 작동하지 않습니다 ##.
jpaugh

답변:


18

그냥 해:

case $1 in
  (*:*) host=${1%:*} port=${1##*:};;
  (*)   host=$1      port=$default_port;;
esac

유사한 값 ( 포트 부분이 없는 IPv6 주소) 을 설명 case $1하도록 case ${1##*[]]}to 를 변경할 수 있습니다 .$1[::1]

분할하려면 split + glob 연산자를 사용하십시오 (매개 변수를 인용 부호로 묶지 말고 그대로 사용하십시오 ).

set -o noglob # disable glob part
IFS=:         # split on colon
set -- $1     # split+glob

host=$1 port=${2:-$default_port}

(그러나 위의 IPv6 주소와 같이 콜론을 포함하는 호스트 이름은 허용되지 않습니다).

그 split + glob 연산자는 방해가되어 나머지 시간에 많은 해를 끼치므로 필요할 때마다 사용하는 것이 공정한 것처럼 보일 것입니다 (그러나 POSIX sh에는 없음을 고려할 때 특히 사용하는 것이 번거 롭습니다 변수 (위한도, 로컬 영역에 대한 지원을 $IFS여기)이나 옵션 (위한 noglob여기) (비록 ash유도체 좋아 dash함께 AT & T의 구현과 (DO 그들 중 일부 ksh, zshbash상기 4.4))는.

참고 IFS=: read A B <<< "$1"자신의 몇 가지 문제가 있습니다 :

  • -r백 슬래시가 특수 처리를 수행한다는 것을 잊어 버렸습니다 .
  • 그것은 분할 것이다 [::1]:443[하고 :1]:443대신 [(과 빈 문자열에 대해 사용자가 필요할 것 IFS=: read -r A B rest_ignored또는 [::1]443) (하는 당신이 방법을 사용할 수 없습니다
  • 그것은 개행 문자의 첫 번째 발생을지나 모든 것을 제거하므로 임의의 문자열과 함께 사용할 수 없습니다 ( 또는 -d ''in 을 사용 하고 데이터에 NUL 문자가 포함되어 있지 않는 한 herestrings 또는 heredocs는 추가 줄 바꿈 문자!)zshbash
  • in zsh(구문이 나오는 곳) 및 bash, 여기서 문자열은 임시 파일을 사용하여 구현되므로 일반적으로 ${x#y}split 또는 glob 연산자를 사용하는 것보다 덜 효율적 입니다.

7
2018 년 새해 결의안으로, 우리는 모두 IPv6에서 깨질 스크립트 작성을 중단해야합니다.
Philippos

@Philippos가 2 주 늦었습니다!
RonJohn

@ RonJohn : 어떻게 든 20 년이 너무 늦었습니다.
Philippos

6

:별도의 문장에서 제거하십시오 . 또한 입력에서 $ host를 제거하여 포트를 가져옵니다.

host=${1%:*}
port=${1#"$host"}
port=${port#:}

3

또 다른 생각 :

host=${1%:*}
port=${1##*:}
[ "$port" = "$1" ] && port=''

1

here 문자열은 단일 행 here 문서의 구문 바로 가기입니다.

$ set myhost:1234
$ IFS=: read A B <<EOF
> $1
> EOF
$ echo "$A"
myhost
$ echo "B"
1234
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.