내 dash
스크립트는 다음과 같은 형식의 매개변수를 사용합니다 hostname:port
.
myhost:1234
포트는 선택 사항입니다. 즉, 다음과 같습니다.
myhost
호스트와 포트를 별도의 변수로 읽어야 합니다. 첫 번째 경우에는 다음과 같이 할 수 있습니다.
HOST=${1%%:*}
PORT=${1##*:}
그러나 두 번째 경우에는 포트가 생략되면 작동하지 않으며 echo ${1##*:}
빈 문자열이 아닌 호스트 이름만 반환됩니다.
Bash에서는 다음과 같이 할 수 있습니다.
IFS=: read A B <<< asdf:111
하지만 여기는 dash
.
외부 프로그램 ( 등) :
을 호출하지 않고 문자열을 대시로 나눌 수 있나요 ?awk
tr
답변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
( noglob
this ) (비록 ash
유사한 파생 상품도 dash
그 중 일부입니다( 4.4 이상의 ksh
AT &T zsh
구현 도 포함)).bash
그 IFS=: read A B <<< "$1"
자체로 몇 가지 문제가 있다는 점에 유의하세요.
-r
이는 백슬래시가 특별한 처리를 거쳐야 한다는 것을 잊고 있는 것입니다 .[::1]:443
그것은 and[
대신:1]:443
에[
빈 문자열 로 분할됩니다 (이를 위해서는IFS=: read -r A B rest_ignored
or[::1]
and가 필요합니다443
(이를 위해서는 해당 방법을 사용할 수 없습니다).- 개행이 처음 발생한 이후의 모든 항목을 제거하므로 임의의 문자열에서는 작동하지 않습니다(또는 내에서 사용하지 않고
-d ''
데이터zsh
에bash
NUL 문자가 포함되어 있지 않은 경우). 그러나 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