쉘 스크립트에서 문자열을 배열로 변환하는 방법

쉘 스크립트에서 문자열을 배열로 변환하는 방법

내가 읽고Bash에서 문자열을 배열로 분할하는 방법그런데 이 질문은 저랑 좀 다른 것 같아서 제 데이터를 활용해서 질문해보겠습니다.

STDIN에서 다음 줄이 있습니다.

(5,[a,b,c,d,e,f,g,h,i,j])

5개가 내 그룹 ID이고 문자는 배열(그룹 데이터)의 값입니다. 그룹 ID를 var에 넣고 문자를 사용할 수 있는 곳에 넣어야 합니다.IFS=',' read -r -a array <<< "$tline"

답변1

bkpIFS="$IFS"

IFS=',()][' read -r -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j])"
echo ${array[@]}    ##Or printf "%s\n" ${array[@]}
5 a b c d e f g h i j

IFS="$bkpIFS"

설명하다:

  • 먼저 기본/현재를 백업해야 합니다.쉘 IFS그리고 bkpIFS="$IFS";
  • 그런 다음 IFS를 구분 기호 집합 ,, (, ), 으로 설정합니다 . 이는 입력 문자열이 하나 이상의 구분 기호로 구분될 수 있음 ][의미합니다 .IFS=',()]['

  • 다음으로 라인을 읽고 위에서 정의한 IFS를 기반으로 들어오는 입력 문자열에서 호출되는 read -r -a array배열로 분할합니다.array여기에 있는 문자열방법. 이 옵션은 입력 시 백슬래시를 확장하지 않도록 -r명령에 지시합니다 .read\

    IFS=',()][' read -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j,\,k])"
    echo ${array[@]}
    5 a b c d e f g h i j ,k
    

    끝을 보아라,k이는 옵션 read없이 입력에 백슬래시가 있기 때문에 -r발생합니다 .

  • echo ${array[@]}배열의 모든 요소를 ​​인쇄하고 있습니다 . 바라보다$*와 $@의 차이점은 무엇인가요?그리고자일스의 대답${array[@]}거기 에 대한 자세한 내용이 있습니다.

  • printf "%s\n" ${array[@]}배열 요소를 인쇄하는 다른 방법이 있습니다 .

  • printf "%s\n" ${array[INDEX]}이제 배열의 특정 요소를 사용하거나 인쇄할 수 있습니다 echo ${array[INDEX]}.

  • IFS아, 죄송합니다. 쉘에 다시 보고하는 것을 잊었습니다 . IFS="$bkpIFS":)

또는 awksplit기능을 사용하십시오.

awk '{split($0,arr,/[][,)(]/)} 
    END{for (x in arr) printf ("%s ",arr[x]);printf "\n"}' <<<"(5,[a,b,c,d,e,f,g,h,i,j])"

설명하다:

  • [...]다시 말하지만, using 함수 /[...]/의 최신 구현에서 지원되는 정규식 상수에 정의된 구분 기호 그룹을 기반으로 전체 입력 줄을 분할합니다 .awksplit더 읽어보세요기능 섹션에서 split().

  • 다음 END{for (x in arr) printf ("%s ",arr[x]); ...}으로 배열을 반복 arr하고 해당 값을 인쇄합니다. x이는 다음을 가리킨다.색인배열 arr요소. 자세히 알아보기awkBEGIN/END 규칙.

다음으로 측면 리디렉션Bash에서 배열에 요소를 추가/제거하는 방법은 무엇입니까?.

답변2

data=$(tr -d '[]()' | tr ',' '\n')

readarray -t -n 1 group   <<<"$data"
readarray -t -s 1 letters <<<"$data"

printf 'group = %s\n' "$group"
printf 'data: %s\n' "${letters[@]}"

이것은 먼저 표준 입력에 도착하는 입력 데이터의 모든 합계를 삭제한 ()다음 쉼표를 줄 바꿈으로 바꾸고 결과를 에 할당합니다.[]trdata

그런 다음 이를 사용하여 readarray이 데이터를 구문 분석합니다.

첫 번째 호출에서는 첫 번째 항목( 포함)만 읽고 -n 1이를 변수에 할당합니다 group.

두 번째 호출에서는 readarray첫 번째 항목( 포함 -s 1)을 건너뛰고 나머지 항목을 배열에 할당합니다 letters.

각 항목에서 -t실제 개행 문자를 제거합니다.

group이는 배열이지만 하나의 요소만 포함 하므로 $group.

$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
group = 5
data: a
data: b
data: c
data: d
data: e
data: f
data: g
data: h
data: i
data: j

다음은 문자열에 쉼표를 유지하고 readline이를 사용하여 항목을 구분하지만 어떤 이유로 마지막 요소 letters끝에 개행 문자가 있습니다.

data=$(tr -d '[]()')
readarray -d, -t -s 1 letters <<<"$data"

printf '>%s<\n' "${letters[@]}"

달리기:

$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
>a<
>b<
>c<
>d<
>e<
>f<
>g<
>h<
>i<
>j
<

답변3

POSIX적으로:

string='(5,[a,b,c,d,e,f,g,h,i,j])'
set -o noglob
IFS=',['
string=${string#'('}
string=${string%'])'}
set -- $string''
gid=$1; shift 2
printf '%s\n' "gid=$gid; group-data:"
printf '   <%s>\n' "$@"

그룹 데이터 필드의 모든 값(개행 문자 포함)에 대해 작동해야 합니다.

답변4

도구를 사용하여 구두점을 제거 sed하면 해당 줄에서 숫자와 문자만 얻을 수 있습니다.

a="(5,[a,b,c,d,e,f,g,h,i,j])"

echo $a | sed 's/[[:punct:]]/ /g'

산출:

5  a b c d e f g h i j 

관련 정보