Bash에서 구분 기호의 문자열을 분할하려면 어떻게 해야 합니까?
다음 문자열이 변수에 저장되어 있습니다.
IN="bla@some.com;john@home.com"
저는 제이저다같줄나싶누습다니고을이음과는▁by▁the▁strings다싶니습▁now▁split이나▁would제▁like▁i로 줄을 나누려고 합니다.;구분 기호를 사용하여 다음을 수행합니다.
ADDR1="bla@some.com"
ADDR2="john@home.com"
꼭 한 것은 아닙니다.ADDR1그리고.ADDR2◦라면 훨씬 더 만약 그것들이 배열의 요소라면 훨씬 더 좋습니다.
아래 답변에서 제안한 결과, 저는 다음과 같은 결과를 얻었습니다.
#!/usr/bin/env bash
IN="bla@some.com;john@home.com"
mails=$(echo $IN | tr ";" "\n")
for addr in $mails
do
echo "> [$addr]"
done
출력:
> [bla@some.com]
> [john@home.com]
Internal_field_separator(IFS)를 다음으로 설정하는 솔루션이 있었습니다.;는 그 대답에 일이 잘요, 요? 어떻게 재설정합니까?IFS기본값으로 되돌리시겠습니까?
다시:IFS해결책, 나는 이것을 시도했고 그것은 효과가 있다, 나는 오래된 것을 유지합니다.IFS복원합니다.
IN="bla@some.com;john@home.com"
OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
echo "> [$x]"
done
IFS=$OIFS
그나저나, 내가 시도했을 때.
mails2=($IN)
할 때 첫 번째 줄만 .$IN그건 효과가 있다.
IFS(Internal Field Separator) 변수를 설정한 다음 이 변수를 배열로 구문 분석할 수 있습니다.명령에서 이 작업이 발생하면 다음에 대한 할당이IFS명령의합니다( 해단명으으환발만서다로니생합에경의(으)로).read)에IFS변수 값을 배열로 변환하여 반복할 수 있습니다.
에서는 이예에다음구로항분목한된줄분다로 된 한 합니다.;배열로 밀어넣기:
IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
# process "$i"
done
는 이다예는전내처위것다입의 전체 하기 위한 입니다.$IN의 입력 이 나의입라인다이같음때구이다로 ;:
while IFS=';' read -ra ADDR; do
for i in "${ADDR[@]}"; do
# process "$i"
done
done <<< "$IN"
IN="bla@some.com;john@home.com"
arrIN=(${IN//;/ })
echo ${arrIN[1]} # Output: john@home.com
설명:
이 은 이구은모대발다체니의 합니다.';' (초기의초)//는 global replace를 의미하며, 은 " replace"입니다.IN와 함께' '(단일 공백), 공백으로 구분된 문자열을 배열로 해석합니다(주변 괄호에서 수행됨).
각각을 바꾸기 위해 곱슬곱슬한 괄호 안에 사용되는 구문';'의 ' '문자를 매개 변수 확장이라고 합니다.
일반적인 gotchas는 다음과 같습니다.
- 원래 문자열에 공백이 있으면 IFS를 사용해야 합니다.
IFS=':'; arrIN=($IN); unset IFS;
- 원래 문자열에 공백이 있고 구분 기호가 새 줄인 경우 다음을 사용하여 IFS를 설정할 수 있습니다.
IFS=$'\n'; arrIN=($IN); unset IFS;
저는 몇 가지 답변을 보았습니다.cut명령입니다. 하지만 모두 삭제되었습니다.아무도 그것에 대해 자세히 설명하지 않은 것은 좀 이상합니다. 왜냐하면 이 명령어는 특히 구분된 로그 파일을 구문 분석하는 데 더 유용한 명령어 중 하나라고 생각하기 때문입니다.
스크립트 , " " " " bash" " " " " " " " " "tr아마도 더 효율적일 것입니다.cut사용할 수 있으며 특정 필드를 중간에서 끌어오려는 경우 더 효과적입니다.
예:
$ echo "bla@some.com;john@home.com" | cut -d ";" -f 1
bla@some.com
$ echo "bla@some.com;john@home.com" | cut -d ";" -f 2
john@home.com
이를 반복하여 -f 매개변수를 반복하여 각 필드를 개별적으로 풀링할 수 있습니다.
이 기능은 다음과 같은 행으로 구분된 로그 파일이 있을 때 더욱 유용합니다.
2015-04-27|12345|some action|an attribute|meta data
cut하기에 매우 편리합니다.cat이 파일을 선택하고 추가 처리를 위해 특정 필드를 선택합니다.
즉시 처리해도 괜찮으시다면 다음과 같이 처리하겠습니다.
for i in $(echo $IN | tr ";" "\n")
do
# process
done
이러한 루프를 사용하여 배열을 초기화할 수 있지만 더 쉬운 방법이 있을 수 있습니다.
호환되는 답변
bash에서 이것을 하는 많은 다른 방법들이 있습니다.
하지만 먼저 주의해야 할 점은bash다른 셸에서는 작동하지 않는 많은 특수 기능(바시즘이라고 함)이 있습니다.
특히 이 게시물의 솔루션뿐만 아니라 스레드의 다른 솔루션에 사용되는 배열, 연관 배열 및 패턴 대체는 바시즘이며 많은 사람들이 사용하는 다른 셸에서는 작동하지 않을 수 있습니다.
예를 들어, 나의 데비안 GNU/리눅스에는 dash라는 표준 셸이 있습니다. 나는 ksh라는 다른 셸을 사용하는 것을 좋아하는 많은 사람들을 알고 있습니다. 그리고 그의 셸 인터프리터(ash)가 있는 busybox라는 특별한 도구도 있습니다.
posix 셸 호환 답변은 이 답변의 마지막 부분으로 이동하십시오!
요청된 문자열
위 질문에서 분할할 문자열은 다음과 같습니다.
IN="bla@some.com;john@home.com"
이 문자열의 수정된 버전을 사용하여 다른 솔루션이 손상될 수 있는 공백이 포함된 문자열에 대해 솔루션이 견고한지 확인합니다.
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
bash의 구분 기호를 기준으로 문자열 분할(버전 >=4.2)
순수하게 bash요소를 IFS(입력 필드 구분 기호)의 임시 값으로 분할하여 배열을 만들 수 있습니다.IFS는, 무엇보다도,bash배열을 정의할 때 요소 사이의 구분 기호로 처리해야 하는 문자:
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
# save original IFS value so we can restore it later
oIFS="$IFS"
IFS=";"
declare -a fields=($IN)
IFS="$oIFS"
unset oIFS
의 신버전에서bash명령 앞에 IFS 정의를 붙이면 해당 명령에 대한 IFS만 변경되고 즉시 이전 값으로 재설정됩니다.즉, 위의 작업을 한 줄로 수행할 수 있습니다.
IFS=\; read -a fields <<<"$IN"
# after this command, the IFS resets back to its previous value (here, the default):
set | grep ^IFS=
# IFS=$' \t\n'
는 리우는 그이끈라는 문자열을 볼 수 있습니다.IN는 라는이어저레장습니다었되라는 에 저장되었습니다.fields세미콜론에서 분할:
set | grep ^fields=\\\|^IN=
# fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>")
# IN='bla@some.com;john@home.com;Full Name <fulnam@other.org>'
을 (으)로 .declare -p:)
declare -p IN fields
# declare -- IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
# declare -a fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>")
:read호출된 포크나 외부 리소스가 없기 때문에 분할을 수행하는 가장 빠른 방법입니다.
배열이 정의되면 간단한 루프를 사용하여 각 필드(또는 지금 정의한 배열의 각 요소)를 처리할 수 있습니다.
# `"${fields[@]}"` expands to return every element of `fields` array as a separate argument
for x in "${fields[@]}" ;do
echo "> [$x]"
done
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
또는 시프트 방식을 사용하여 처리한 후 어레이에서 각 필드를 삭제할 수 있습니다.
while [ "$fields" ] ;do
echo "> [$fields]"
# slice the array
fields=("${fields[@]:1}")
done
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
또한 어레이에서 간단한 인쇄만 원할 경우에는 루프할 필요가 없습니다.
printf "> [%s]\n" "${fields[@]}"
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
업데이트: 최근 bash > = 4.4
의 신버전에서bash명령을 사용하여 재생할 수도 있습니다.mapfile:
mapfile -td \; fields < <(printf "%s\0" "$IN")
이 구문은 특수 문자, 새 줄 및 빈 필드를 유지합니다!
빈 필드를 포함하지 않으려면 다음을 수행할 수 있습니다.
mapfile -td \; fields <<<"$IN"
fields=("${fields[@]%$'\n'}") # drop '\n' added by '<<<'
와 함께mapfile또한 배열 선언을 건너뛰고 구분된 요소 위에 암묵적으로 "루프"하여 각 요소에 대한 함수를 호출할 수 있습니다.
myPubliMail() {
printf "Seq: %6d: Sending mail to '%s'..." $1 "$2"
# mail -s "This is not a spam..." "$2" </path/to/body
printf "\e[3D, done.\n"
}
mapfile < <(printf "%s\0" "$IN") -td \; -c 1 -C myPubliMail
(주: 더)\0형식 문자열의 끝에 있는 빈 필드에 관심이 없거나 필드가 없는 경우에는 형식 문자열의 끝에 있는 것이 유용하지 않습니다.)
mapfile < <(echo -n "$IN") -td \; -c 1 -C myPubliMail
# Seq: 0: Sending mail to 'bla@some.com', done.
# Seq: 1: Sending mail to 'john@home.com', done.
# Seq: 2: Sending mail to 'Full Name <fulnam@other.org>', done.
아니면 당신은 사용할 수 있습니다.<<<그리고 기능 본체에는 다음과 같이 새로운 줄을 추가하는 처리가 포함되어 있습니다.
myPubliMail() {
local seq=$1 dest="${2%$'\n'}"
printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest"
# mail -s "This is not a spam..." "$dest" </path/to/body
printf "\e[3D, done.\n"
}
mapfile <<<"$IN" -td \; -c 1 -C myPubliMail
# Renders the same output:
# Seq: 0: Sending mail to 'bla@some.com', done.
# Seq: 1: Sending mail to 'john@home.com', done.
# Seq: 2: Sending mail to 'Full Name <fulnam@other.org>', done.
셸의 구분 기호를 기준으로 문자열 분할
▁할 수 경우bash또는 다양한 셸에서 사용할 수 있는 무언가를 작성하려면 바시즘을 사용할 수 없는 경우가 많습니다. 여기에는 위의 솔루션에서 사용한 어레이도 포함됩니다.
그러나 문자열의 "요소"를 루프하기 위해 배열을 사용할 필요는 없습니다.패턴의 처음 또는 마지막 발생에서 문자열의 하위 문자열을 삭제하기 위해 많은 셸에서 사용되는 구문이 있습니다.참고:*는 0자 이상의 문자를 나타내는 와일드카드입니다.
(지금까지 게시된 솔루션에 이러한 접근 방식이 없다는 것이 제가 이 답변을 쓰는 주된 이유입니다;)
${var#*SubStr} # drops substring from start of string up to first occurrence of `SubStr`
${var##*SubStr} # drops substring from start of string up to last occurrence of `SubStr`
${var%SubStr*} # drops substring from last occurrence of `SubStr` to end of string
${var%%SubStr*} # drops substring from first occurrence of `SubStr` to end of string
Score_Under에서 설명한 바와 같이:
#그리고.%문자열의 시작과 끝에서 각각 가장 짧은 일치 하위 문자열을 삭제합니다.
##그리고.%%가능한 가장 긴 일치 하위 문자열을 삭제합니다.
위의 구문을 사용하여 구분 기호 뒤에 있는 하위 문자열을 삭제하여 문자열에서 하위 문자열 "요소"를 추출하는 접근법을 만들 수 있습니다.
아래 코드 블록은 bash(Mac OS 포함)에서 잘 작동합니다.bash), dash, ksh, lksh, yash, zsh 및 busybox의 ash:
(Adam Katz의 코멘트 덕분에 이 루프를 훨씬 더 간단하게 만들 수 있습니다!)
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
while [ "$IN" != "$iter" ] ;do
# extract the substring from start of string up to delimiter.
iter=${IN%%;*}
# delete this first "element" AND next separator, from $IN.
IN="${IN#$iter;}"
# Print (or doing anything with) the first "element".
printf '> [%s]\n' "$iter"
done
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
안 그래요?cut?
cut큰 파일의 열을 추출하는 데 유용하지만 포크를 반복적으로 수행합니다(var=$(echo ... | cut ...) 살상을 빠게과잉살됩이니다상르!됩!
다음은 올바른 구문으로, 다음을 사용하여 많은 posixshell에서 테스트되었습니다.cutDougW의 다른 답변에서 제안한 대로:
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
i=1
while iter=$(echo "$IN"|cut -d\; -f$i) ; [ -n "$iter" ] ;do
printf '> [%s]\n' "$iter"
i=$((i+1))
done
저는 실행 시간을 비교하기 위해 이것을 썼습니다.
내 라즈베리 파이에서, 이것은 다음과 같습니다.
$ export TIMEFORMAT=$'(%U + %S) / \e[1m%R\e[0m : %P '
$ time sh splitDemo.sh >/dev/null
(0.000 + 0.019) / 0.019 : 99.63
$ time sh splitDemo_cut.sh >/dev/null
(0.051 + 0.041) / 0.188 : 48.98
전체 실행 시간이 10배 정도 긴 경우, 포크 1개를 사용하여cut분야별로!
이것은 저에게 효과가 있었습니다.
string="1;2"
echo $string | cut -d';' -f1 # output is 1
echo $string | cut -d';' -f2 # output is 2
저는 AWK가 당신의 문제를 해결할 수 있는 최고의 효율적인 명령이라고 생각합니다.AWK는 기본적으로 거의 모든 Linux 배포판에 포함되어 있습니다.
echo "bla@some.com;john@home.com" | awk -F';' '{print $1,$2}'
줄 것입니다
bla@some.com john@home.com
물론 각 전자 메일 주소는 Awk 인쇄 필드를 재정의하여 저장할 수 있습니다.
이 접근 방식은 어떻습니까?
IN="bla@some.com;john@home.com"
set -- "$IN"
IFS=";"; declare -a Array=($*)
echo "${Array[@]}"
echo "${Array[0]}"
echo "${Array[1]}"
echo "bla@some.com;john@home.com" | sed -e 's/;/\n/g'
bla@some.com
john@home.com
이 기능은 다음과 같습니다.
IN="bla@some.com;john@home.com"
echo ADD1=`echo $IN | cut -d \; -f 1`
echo ADD2=`echo $IN | cut -d \; -f 2`
이 솔루션이 항상 올바른 것은 아닙니다."bla@some.com "만 통과하면 ADD1과 ADD2 모두에 할당됩니다.
Darron의 대답에 대한 다른 견해는 다음과 같습니다.
IN="bla@some.com;john@home.com"
read ADDR1 ADDR2 <<<$(IFS=";"; echo $IN)
어레이를 사용하지 않는 경우 이 라이너 하나는 어떻습니까?
IFS=';' read ADDR1 ADDR2 <<<$IN
Bash에서는 변수에 새 줄이 포함된 경우에도 사용할 수 있는 방탄 방법입니다.
IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
보기:
$ in=$'one;two three;*;there is\na newline\nin this field'
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is
a newline
in this field")'
이것이 작동하는 비결은 다음을 사용하는 것입니다.-d.read( 기호비어 (으)ㄹ 수 있도록,read먹이가 되는 모든 것을 읽도록 강요당합니다.그리고 우리는 밥을 먹습니다.read의 in에 줄않고잇지을분 printf또한 구분 기호를 입력합니다.printf이 확게전하록위기해도달로 read뒤에 구분 기호가 있습니다.그게 없으면,read잠재적인 후행 빈 필드를 자릅니다.
$ in='one;two;three;' # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'
뒤에 오는 빈 필드가 보존됩니다.
Bash에 대한 업데이트 » 4.4
4, Bash 4.4에 된 기본제mapfile (일명)readarray은 (으) 를 지원합니다.-d구분 기호를 지정하는 옵션입니다.따라서 다른 표준 방법은 다음과 같습니다.
mapfile -d ';' -t array < <(printf '%s;' "$in")
IFS를 설정하지 않음
대장이 하나만 있는 경우 다음 작업을 수행할 수 있습니다.
a="foo:bar"
b=${a%:*}
c=${a##*:}
다음을 얻을 수 있습니다.
b = foo
c = bar
여기 깨끗한 3-라이너가 있습니다.
in="foo@bar;bizz@buzz;fizz@buzz;buzz@woof"
IFS=';' list=($in)
for item in "${list[@]}"; do echo $item; done
IFS하고 구 기 기 단 호 를 구 어 합 니 분 다 를 로 분 준 으 니 합 ▁delim 다 구 분 it ▁based ▁words()배열을 만드는 데 사용됩니다.그리고나서[@]각 항목을 별도의 단어로 반환하는 데 사용됩니다.
그이코있복필요다니합원도으면드가후▁다▁if▁도 복원해야 합니다.$IFS,예.unset IFS.
다음 Bash/zsh 함수는 두 번째 인수에 의해 지정된 구분 기호에 대한 첫 번째 인수를 분할합니다.
split() {
local string="$1"
local delimiter="$2"
if [ -n "$string" ]; then
local part
while read -d "$delimiter" part; do
echo $part
done <<< "$string"
echo $part
fi
}
예를 들어, 명령어는
$ split 'a;b;c' ';'
수확량
a
b
c
예를 들어, 이 출력은 다른 명령에 연결될 수 있습니다.예:
$ split 'a;b;c' ';' | cat -n
1 a
2 b
3 c
제공된 다른 솔루션과 비교하여 이 솔루션은 다음과 같은 이점을 제공합니다.
IFS재정의되지 않음:로컬 변수의 동적 범위 지정으로 인해 재정의IFS루프를 통해 루프 내에서 수행되는 함수 호출에 새 값이 누출됩니다.배열이 사용되지 않음: 다음을 사용하여 문자열을 배열로 읽기
read깃발이 필요합니다.-a바시와-Azsh 단위로
원하는 경우 다음과 같이 스크립트에 함수를 넣을 수 있습니다.
#!/usr/bin/env bash
split() {
# ...
}
split "$@"
당신은 많은 상황에 어색함을 적용할 수 있습니다.
echo "bla@some.com;john@home.com"|awk -F';' '{printf "%s\n%s\n", $1, $2}'
또한 당신은 이것을 사용할 수 있습니다.
echo "bla@some.com;john@home.com"|awk -F';' '{print $1,$2}' OFS="\n"
다음과 같은 간단하고 현명한 방법이 있습니다.
echo "add:sfff" | xargs -d: -i echo {}
그러나 gnuxargs를 사용해야 합니다. BSD xargs는 -d 구분을 지원할 수 없습니다.만약 당신이 나처럼 애플맥을 사용한다면요.gnxargs를 설치할 수 있습니다.
brew install findutils
그리고나서
echo "add:sfff" | gxargs -d: -i echo {}
여기에 몇 가지 멋진 대답이 있습니다(오류자 등). 하지만 다른 언어로 쪼개지는 것과 유사한 것에 대해 - 제가 원래 질문을 의미하는 바입니다 - 저는 이것을 결정했습니다.
IN="bla@some.com;john@home.com"
declare -a a="(${IN//;/ })";
지금이다${a[0]},${a[1]}등 당신이 예상하는 것과 같은 영역.사용하다${#a[*]}기간의 수에 대하여물론 반복하자면,
for i in ${a[*]}; do echo $i; done
중요 참고:
이것은 걱정할 공간이 없는 경우에 효과가 있는데, 이것은 나의 문제를 해결했지만, 당신의 문제를 해결하지 못할 수도 있습니다.다음 항목으로 이동$IFS이 경우 해결책이 필요합니다.
답이 너무 많고 복잡합니다.더 간단한 솔루션을 사용해 보십시오.
echo "string1, string2" | tr , "\n"
tr(read, translate)는 입력에서 첫 번째 인수를 두 번째 인수로 바꿉니다.
그렇게tr"\n"은 입력에서 쉼표를 새 줄 문자로 바꾸면 다음과 같습니다.
string1
string2
공간이 없다면, 왜 이것이 아닌가요?
IN="bla@some.com;john@home.com"
arr=(`echo $IN | tr ';' ' '`)
echo ${arr[0]}
echo ${arr[1]}
이것이 그 일을 하는 가장 간단한 방법입니다.
spo='one;two;three'
OIFS=$IFS
IFS=';'
spo_array=($spo)
IFS=$OIFS
echo ${spo_array[*]}
이미 제공된 환상적인 답변과는 별개로, 데이터를 인쇄하는 것이 문제라면 사용을 고려할 수 있습니다.awk:
awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
필드 구분 기호를 다음으로 설정합니다.;그래서 그것은 들판을 순환할 수 있습니다.for루프하고 인쇄합니다.
시험
$ IN="bla@some.com;john@home.com"
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
> [bla@some.com]
> [john@home.com]
다른 입력의 경우:
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;c d;e_;f"
> [a]
> [b]
> [c d]
> [e_]
> [f]
IN="bla@some.com;john@home.com"
IFS=';'
read -a IN_arr <<< "${IN}"
for entry in "${IN_arr[@]}"
do
echo $entry
done
산출량
bla@some.com
john@home.com
시스템 : Ubuntu 12.04.1
사용set로드할 수 있는 기본 제공$@배열:
IN="bla@some.com;john@home.com"
IFS=';'; set $IN; IFS=$' \t\n'
그런 다음 파티를 시작합니다.
echo $#
for a; do echo $a; done
ADDR1=$1 ADDR2=$2
bash 어레이가 필요하지 않은 두 가지 본과 같은 대안:
사례 1: 멋지고 단순하게 유지:새 줄을 레코드 구분 기호로 사용...예를 들면
IN="bla@some.com
john@home.com"
while read i; do
# process "$i" ... eg.
echo "[email:$i]"
done <<< "$IN"
참고: 이 첫 번째 경우에는 목록 조작을 지원하기 위해 분기된 하위 프로세스가 없습니다.
아이디어: 내부적으로 NL을 광범위하게 사용하고, 외부적으로 최종 결과를 생성할 때만 다른 RS로 변환하는 것이 가치가 있을 수 있습니다.
사례 2: ";"를 기록 구분 기호로 사용...예를 들면
NL="
" IRS=";" ORS=";"
conv_IRS() {
exec tr "$1" "$NL"
}
conv_ORS() {
exec tr "$NL" "$1"
}
IN="bla@some.com;john@home.com"
IN="$(conv_IRS ";" <<< "$IN")"
while read i; do
# process "$i" ... eg.
echo -n "[email:$i]$ORS"
done <<< "$IN"
두 경우 모두 루프가 완료된 후 루프 내에서 하위 목록을 구성할 수 있습니다.이 기능은 목록을 파일에 저장하는 대신 메모리에서 목록을 조작할 때 유용합니다.{p.s. 침착하고 B-)}
Android 셸에서 제안된 대부분의 방법은 작동하지 않습니다.
$ IFS=':' read -ra ADDR <<<"$PATH"
/system/bin/sh: can't create temporary file /sqlite_stmt_journals/mksh.EbNoR10629: No such file or directory
작동하는 기능은 다음과 같습니다.
$ for i in ${PATH//:/ }; do echo $i; done
/sbin
/vendor/bin
/system/sbin
/system/bin
/system/xbin
//글로벌 교체를 의미합니다.
IN='bla@some.com;john@home.com;Charlie Brown <cbrown@acme.com;!"#$%&/()[]{}*? are no problem;simple is beautiful :-)'
set -f
oldifs="$IFS"
IFS=';'; arrayIN=($IN)
IFS="$oldifs"
for i in "${arrayIN[@]}"; do
echo "$i"
done
set +f
출력:
bla@some.com
john@home.com
Charlie Brown <cbrown@acme.com
!"#$%&/()[]{}*? are no problem
simple is beautiful :-)
설명:괄호()를 사용한 간단한 할당은 올바른 IFS가 있으면 세미콜론으로 구분된 목록을 배열로 변환합니다.표준 FOR 루프는 해당 배열의 개별 항목을 평소와 같이 처리합니다.IN 변수에 대해 지정된 리스트는 "하드" 따옴표로 묶어야 합니다. 즉, 단일 눈금으로 따옴표로 묶어야 합니다.
Bash는 할당을 명령과 동일한 방식으로 처리하지 않으므로 IFS를 저장하고 복원해야 합니다.다른 해결 방법은 할당을 함수 내부에 래핑하고 수정된 IFS로 해당 함수를 호출하는 것입니다.이 경우 IFS를 별도로 저장/복원할 필요가 없습니다.그것을 지적해 준 "비즈"에게 감사드립니다.
제 대답은 이렇습니다!
DELIMITER_VAL='='
read -d '' F_ABOUT_DISTRO_R <<"EOF"
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
NAME="Ubuntu"
VERSION="14.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.4 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
EOF
SPLIT_NOW=$(awk -F$DELIMITER_VAL '{for(i=1;i<=NF;i++){printf "%s\n", $i}}' <<<"${F_ABOUT_DISTRO_R}")
while read -r line; do
SPLIT+=("$line")
done <<< "$SPLIT_NOW"
for i in "${SPLIT[@]}"; do
echo "$i"
done
이 접근 방식이 "최고"인 이유는 무엇입니까?
두 가지 이유 때문에:
- 구분 기호에서 벗어날 필요는 없습니다.
- 빈 공간에는 문제가 없습니다.값은 배열에서 올바르게 구분됩니다.
';'로 구분된 문자열을 배열로 분할하는 한 줄기는 다음과 같습니다.
IN="bla@some.com;john@home.com"
ADDRS=( $(IFS=";" echo "$IN") )
echo ${ADDRS[0]}
echo ${ADDRS[1]}
이는 IFS를 하위 셸에서만 설정하므로 값을 저장하고 복원할 필요가 없습니다.
언급URL : https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash
'programing' 카테고리의 다른 글
| UPDLOCK, HOLDLOCK에 대해 혼동됨 (0) | 2023.04.26 |
|---|---|
| NSDate에 1일을 추가하려면 어떻게 해야 합니까? (0) | 2023.04.26 |
| Linux에서 디렉토리를 루프오버하는 방법 (0) | 2023.04.21 |
| Storyboard 프로토타입 셀(Xcode 6, iOS 8 SDK)에서 UICollectionViewCell contentView 프레임의 자동 크기 조정 문제는 iOS 7에서만 발생합니다. (0) | 2023.04.21 |
| .NET 설정(app.config/web.config/settings).설정) (0) | 2023.04.21 |