/bin/sh의 콜론으로 구분된 문자열

/bin/sh의 콜론으로 구분된 문자열

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

myhost:1234

포트는 선택 사항입니다. 즉, 다음과 같습니다.

myhost

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

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

그러나 두 번째 경우에는 포트가 생략되면 작동하지 않으며 echo ${1##*:}빈 문자열이 아닌 호스트 이름만 반환됩니다.

Bash에서는 다음과 같이 할 수 있습니다.

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

하지만 여기는 dash.

외부 프로그램 ( 등) :을 호출하지 않고 문자열을 대시로 나눌 수 있나요 ?awktr

답변1

그냥 해:

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

유사한 값을 고려하여 case $1변경 해야 할 수도 있습니다 (case ${1##*[]]}$1[::1]포트부분).

분할하려면 다음을 사용할 수 있습니다.분할+전역연산자(인용부호 없이 매개변수 확장을 남겨두세요), 이것이 바로 그 용도이기 때문입니다:

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( noglobthis ) (비록 ash유사한 파생 상품도 dash그 중 일부입니다( 4.4 이상의 kshAT &T zsh구현 도 포함)).bash

IFS=: read A B <<< "$1"자체로 몇 가지 문제가 있다는 점에 유의하세요.

  • -r이는 백슬래시가 특별한 처리를 거쳐야 한다는 것을 잊고 있는 것입니다 .
  • [::1]:443그것은 and [대신 :1]:443[빈 문자열 로 분할됩니다 (이를 위해서는 IFS=: read -r A B rest_ignoredor [::1]and가 필요합니다 443(이를 위해서는 해당 방법을 사용할 수 없습니다).
  • 개행이 처음 발생한 이후의 모든 항목을 제거하므로 임의의 문자열에서는 작동하지 않습니다(또는 내에서 사용하지 않고 -d ''데이터 zshbashNUL 문자가 포함되어 있지 않은 경우). 그러나 herestrings(또는 heredocs)는 추가 문자열을 추가합니다. 줄 바꿈 문자!)
  • zsh(문법 소스) 및 에서 bash문자열은 임시 파일을 사용하여 구현되므로 일반적으로 ${x#y}또는 분할+glob 연산자를 사용하는 것보다 효율성이 떨어집니다.

답변2

:별도의 명령문에서 제거하고 포트를 얻으려면 입력에서 $host를 제거하십시오.

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

답변3

또 다른 아이디어:

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

답변4

이 문자열은 여기에서 한 줄 문서에 대한 구문 바로가기일 뿐입니다.

$ set myhost:1234
$ IFS=: read A B <<EOF
> $1
> EOF
$ echo "$A"
myhost
$ echo "B"
1234

관련 정보