Bash : 문자열을 문자 배열로 분할
구분 기호를 기반으로하지 않고 배열 인덱스 당 하나의 문자 만 기반으로하는 문자 배열로 분할하려는 Bash 셸 스크립트에 문자열이 있습니다. 어떻게 할 수 있습니까?
이상적으로는 외부 프로그램을 사용하지 않습니다.
다시 말하겠습니다. 내 목표는 이식성이므로 sed
POSIX 호환 시스템에있을 가능성이 높은 것은 괜찮습니다.
시험
echo "abcdefg" | fold -w1
편집 : 의견에 제안 된보다 우아한 솔루션을 추가했습니다.
echo "abcdefg" | grep -o .
배열 변환없이 이미 각 문자에 개별적으로 액세스 할 수 있습니다.
$ foo="bar"
$ echo ${foo:0:1}
b
$ echo ${foo:1:1}
a
$ echo ${foo:2:1}
r
충분하지 않다면 다음과 같이 사용할 수 있습니다.
$ bar=($(echo $foo|sed 's/\(.\)/\1 /g'))
$ echo ${bar[1]}
a
sed
또는 그와 비슷한 것을 사용할 수 없다면 위의 첫 번째 기술을 원래 문자열의 길이 ( ${#foo}
)를 사용하여 while 루프와 결합 하여 배열을 만들 수 있습니다.
경고 : 문자열에 공백이 포함 된 경우 아래 코드가 작동하지 않습니다. Vaughn Cato의 대답 은 특별한 캐릭터로 살아남을 가능성이 더 높다고 생각 합니다.
thing=($(i=0; while [ $i -lt ${#foo} ] ; do echo ${foo:$i:1} ; i=$((i+1)) ; done))
문자열이 변수 x에 저장되면 개별 문자가 포함 된 배열 y가 생성됩니다.
i=0
while [ $i -lt ${#x} ]; do y[$i]=${x:$i:1}; i=$((i+1));done
0 .. ${#string}-1
for / while 루프 를 사용 하여 반복하는 대신 bash만으로이 작업을 수행 할 수있는 다른 두 가지 방법이 있습니다 . using =~
및 using printf
. ( eval
및 {..}
시퀀스 표현을 사용하는 세 번째 가능성 이 있지만 명확성이 부족합니다.)
bash에서 올바른 환경과 NLS를 사용하면 예상대로 비 ASCII에서 작동 sed
하여 문제가되는 경우, 와 같은 이전 시스템 도구에서 잠재적 인 오류 원인을 제거합니다 . 이는 bash-3.0 (2005 년 출시)에서 작동합니다.
=~
및 정규 표현식을 사용 하여 단일 표현식에서 문자열을 배열로 변환 :
string="wonkabars"
[[ "$string" =~ ${string//?/(.)} ]] # splits into array
printf "%s\n" "${BASH_REMATCH[@]:1}" # loop free: reuse fmtstr
declare -a arr=( "${BASH_REMATCH[@]:1}" ) # copy array for later
이것이 작동하는 방식은 확장을 수행하여 string
각 단일 문자를으로 대체 (.)
한 다음 생성 된 정규식을 그룹화와 일치시켜 각 개별 문자를로 캡처하는 것 BASH_REMATCH[]
입니다. 인덱스 0은 전체 문자열로 설정됩니다. 특수 배열은 읽기 전용이므로 제거 할 수 없습니다 :1
. 필요한 경우 인덱스 0을 건너 뛰도록 배열을 확장 할 때 주의하십시오 . 사소하지 않은 문자열 (> 64 자)에 대한 몇 가지 빠른 테스트는이 방법이 bash 문자열 및 배열 작업을 사용하는 방법 보다 훨씬 빠르다 는 것을 보여줍니다 .
위의 내용은 줄 바꿈이 포함 된 문자열과 함께 작동하며 기본적으로 NUL 을 제외한 모든 항목과 일치=~
하는 POSIX ERE를.
지원합니다 . 즉, 정규식은 REG_NEWLINE
. (POSIX 텍스트 처리 유틸리티 의 동작은 이 점에서 기본적으로 다를 수 있으며 일반적으로 다릅니다.)
두 번째 옵션, 사용 printf
:
string="wonkabars"
ii=0
while printf "%s%n" "${string:ii++:1}" xx; do
((xx)) && printf "\n" || break
done
이 루프는 인덱스 ii
를 증가 시켜 한 번에 한 문자를 인쇄하고 남은 문자가 없을 때 중단됩니다. bash printf
가 오류 상태가 아닌 인쇄 된 문자 수 (C에서와 같이)를 반환 한 경우 대신 인쇄 된 문자 수 xx
를 %n
. (적어도 bash-2.05b까지는 작동합니다.)
bash-3.1을 사용 printf -v var
하면 약간 더 융통성이 있으며 문자를 인쇄하는 것 이외의 작업을 수행하는 경우, 예를 들어 배열을 만드는 경우 문자열 끝에서 떨어지는 것을 방지 할 수 있습니다.
declare -a arr
ii=0
while printf -v cc "%s%n" "${string:(ii++):1}" xx; do
((xx)) && arr+=("$cc") || break
done
string=hello123
for i in $(seq 0 ${#string})
do array[$i]=${string:$i:1}
done
echo "zero element of array is [${array[0]}]"
echo "entire array is [${array[@]}]"
배열의 0 요소는입니다 [h]
. 전체 배열은 [h e l l o 1 2 3 ]
입니다.
가장 간단하고 완벽하며 우아한 솔루션 :
$ read -a ARRAY <<< $(echo "abcdefg" | sed 's/./& /g')
및 테스트
$ echo ${ARRAY[0]}
a
$ echo ${ARRAY[1]}
b
설명 : read -a
stdin을 배열로 읽고 각 배열 항목의 구분자로 공백을 처리하는 변수 ARRAY에 지정합니다.
sed에 문자열을 에코하는 평가는 각 문자 사이에 필요한 공백을 추가합니다.
우리는 사용하고 여기에 문자열을 읽기 명령의 표준 입력을 공급하는 (<<<).
텍스트에 공백이 포함될 수있는 경우 :
eval a=( $(echo "this is a test" | sed "s/\(.\)/'\1' /g") )
$ echo hello | awk NF=NF FS=
h e l l o
또는
$ echo hello | awk '$0=RT' RS=[[:alnum:]]
h
e
l
l
o
이것을 배열에 저장하려면 다음을 수행하십시오.
string=foo
unset chars
declare -a chars
while read -N 1
do
chars[${#chars[@]}]="$REPLY"
done <<<"$string"x
unset chars[$((${#chars[@]} - 1))]
unset chars[$((${#chars[@]} - 1))]
echo "Array: ${chars[@]}"
Array: f o o
echo "Array length: ${#chars[@]}"
Array length: 3
The final x
is necessary to handle the fact that a newline is appended after $string
if it doesn't contain one.
If you want to use NUL-separated characters, you can try this:
echo -n "$string" | while read -N 1
do
printf %s "$REPLY"
printf '\0'
done
AWK is quite convenient:
a='123'; echo $a | awk 'BEGIN{FS="";OFS=" "} {print $1,$2,$3}'
where FS
and OFS
is delimiter for read-in and print-out
For those who landed here searching how to do this in fish:
We can use the builtin string
command (since v2.3.0) for string manipulation.
↪ string split '' abc
a
b
c
The output is a list, so array operations will work.
↪ for c in (string split '' abc)
echo char is $c
end
char is a
char is b
char is c
Here's a more complex example iterating over the string with an index.
↪ set --local chars (string split '' abc)
for i in (seq (count $chars))
echo $i: $chars[$i]
end
1: a
2: b
3: c
zsh solution: To put the scalar string
variable into arr
, which will be an array:
arr=(${(ps::)string})
If you also need support for strings with newlines, you can do:
str2arr(){ local string="$1"; mapfile -d $'\0' Chars < <(for i in $(seq 0 $((${#string}-1))); do printf '%s\u0000' "${string:$i:1}"; done); printf '%s' "(${Chars[*]@Q})" ;}
string=$(printf '%b' "apa\nbepa")
declare -a MyString=$(str2arr "$string")
declare -p MyString
# prints declare -a MyString=([0]="a" [1]="p" [2]="a" [3]=$'\n' [4]="b" [5]="e" [6]="p" [7]="a")
As a response to Alexandro de Oliveira, I think the following is more elegant or at least more intuitive:
while read -r -n1 c ; do arr+=("$c") ; done <<<"hejsan"
ReferenceURL : https://stackoverflow.com/questions/7578930/bash-split-string-into-character-array
'programing' 카테고리의 다른 글
사전에서 클래스 인스턴스 속성을 생성합니까? (0) | 2021.01.17 |
---|---|
Chrome의 눈에 띄지 않는 유효성 검사는 dd / mm / yyyy로 유효성을 검사하지 않습니다. (0) | 2021.01.17 |
공백 만 포함 된 문자열을 감지하는 방법은 무엇입니까? (0) | 2021.01.17 |
Jquery 선택이 + 클래스 (0) | 2021.01.17 |
iOS 7에서 시작하는 동안 상태 표시 줄 스타일을 변경하는 방법 (0) | 2021.01.17 |