쉘에 JavaScript의 "split()"과 같은 것이 있습니까?

쉘에 JavaScript의 "split()"과 같은 것이 있습니까?

split()문자열을 배열로 나누는 것은 JavaScript에서 매우 쉽습니다.

쉘 스크립트는 어떻습니까?

내가 이것을 하고 싶다고 가정해보자:

$ script.sh var1_var2_var3

사용자가 script.sh에 이러한 문자열을 제공하면 var1_var2_var3스크립트 내에서 문자열을 배열로 변환합니다.

array=( var1 var2 var3 )
for name in ${array[@]}; do
    # some code
done

답변1

$varBourne/POSIX와 유사한 쉘에는 목록 컨텍스트에서 인용되지 않은 인수 확장( , $-...), 명령 대체( ) 또는 산술 확장( ) 이 있을 때마다 $(...)호출되는 분할+glob 연산자가 있습니다.$((...))

for name in ${array[@]}실제로 대신 호출했을 때 잘못 호출했습니다 for name in "${array[@]}". (사실 주의해야 할 점은이 연산자를 잘못 호출하면 많은 버그와 보안 취약점이 발생합니다.).

$IFS이 연산자는 분할할 문자를 알려주는 특수 매개변수(그러나 공백, 탭 및 개행 문자는 여기서 특별히 처리됨)와 해당 섹션을 -f비활성화( set -f)하거나 활성화( )하는 옵션 으로 구성됩니다 .set +fglob

또한 Sin은 $IFS원래 (Bourne 쉘에서 $IFS) S구분 기호로 사용되었지만 POSIX 쉘에서는 in의 문자를 다음 $IFS과 같이 처리해야 합니다.구분 기호또는터미네이터(아래 예 참조)

그래서 분할하려면 _:

string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
array=($string) # invoke the split+glob operator

for i in "${array[@]}"; do # loop over the array elements.

차이점을 보려면분할기그리고구분 기호, 시도 해봐:

string='var1_var2_'

var1이렇게 하면 and 로만 분할됩니다 var2(추가 빈 요소 없음).

따라서 JavaScript와 유사하게 만들려면 split()추가 단계가 필요합니다.

string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
temp=${string}_ # add an extra delimiter
array=($temp) # invoke the split+glob operator

( $stringNull을 다음과 같이 분할 합니다.1(아니요0) 요소(예: JavaScript의 split()).

탭, 공백 및 줄 바꿈의 특수 처리를 보려면 다음을 비교하십시오.

IFS=' '; string=' var1  var2  '

(합계를 얻는 var1var2)

IFS='_'; string='_var1__var2__'

'', var1, '', var2, ''.​

zsh쉘은 in 또는 에뮬레이션을 제외하고는 이와 같은 분할+glob 연산자를 암시적으로 호출하지 않습니다 . 거기에서 명시적으로 호출해야 합니다. 분할 부분과 전역 부분(둘 다)의 경우 구분 기호를 지정할 수 있는 분할 연산자도 있습니다.shksh$=string$~string$=~string

array=(${(s:_:)string})

또는 빈 요소를 유지합니다.

array=("${(@s:_:)string}")

있습니다 s.나뉘다, 아니요정의하다$IFS(또한 알려진 POSIX 부적합 사항 도 있습니다 zsh.) split()빈 문자열이 1이 아닌 0개의 요소로 분할된다는 점에서 JavaScript와 다릅니다 .

-splitting과의 주목할만한 차이점 중 하나 는 $IFSstring ${(s:abc:)string}에서 분할이 발생하는 abc반면, ,를 사용하면 또는 에서 IFS=abc분할된다는 것 입니다 .abc

zsh및 의 경우 ksh93공백, 탭 또는 개행 문자에 대한 특수 처리를 두 배로 늘려 제거할 수 있습니다 $IFS.

역사적으로 Bourne 쉘(원조 또는 최신 POSIX 쉘)은 항상 빈 요소를 제거합니다. 또한 기본값이 아닌 $@의 분할 및 확장과 관련된 많은 버그가 있었습니다 $IFS. 예를 들어 IFS=_; set -f; set -- $@와 같지 않습니다 IFS=_; set -f; set -- $1 $2 $3....

정규식을 기준으로 분할

이제 정규식을 기반으로 분할할 수 있는 JavaScript에 더 가까운 것을 얻으려면 split()외부 유틸리티에 의존해야 합니다.

POSIX 도구 상자에는 분할할 수 있는 연산자 awk가 있습니다.split확장 정규식(이것들은 JavaScript가 지원하는 Perl과 유사한 정규식의 하위 집합입니다.)

split() {
  awk -v q="'" '
    function quote(s) {
      gsub(q, q "\\" q q, s)
      return q s q
    }
    BEGIN {
      n = split(ARGV[1], a, ARGV[2])
      for (i = 1; i <= n; i++) printf " %s", quote(a[i])
      exit
    }' "$@"
}
string=a__b_+c
eval "array=($(split "$string" '[_+]+'))"

쉘에는 zshPerl 호환 정규식에 대한 지원이 내장되어 있지만( zsh/pcre모듈에) 이를 사용하여 문자열을 분할하는 것은 상대적으로 번거로울 수 있습니다.

답변2

예, IFS으로 설정하고 사용하세요 _. 그런 다음 백슬래시 확장이 꺼진 상태에서 read -a배열에 저장하는 데 사용됩니다. -r이는 bash에만 해당됩니다. ksh와 zsh는 기능은 유사하지만 구문은 약간 다르며 일반 sh에는 배열 변수가 전혀 없습니다.

$ r="var1_var2_var3"
$ IFS='_' read -r -a array <<< "$r"
$ for name in "${array[@]}"; do echo "+ $name"; done
+ var1
+ var2
+ var3

에서 man bash:

읽다

-ㅏ이름

단어는 0부터 시작하여 배열 변수 aname의 순차 인덱스에 할당됩니다. aname은 새 값이 할당되기 전에 설정 해제됩니다. 다른 이름 매개변수는 무시됩니다.

IFS

내부 필드 구분 기호는 확장 후 단어 분할 및 read 내장 명령을 사용하여 행을 단어로 분할하는 데 사용됩니다. 기본값은 ""입니다.

read첫 번째 개행 문자에서 중지됩니다 . 를 전달하면 -d ''이를 read방지할 수 있지만 이 경우 연산자로 인해 끝에 추가 줄바꿈이 발생합니다 <<<. 수동으로 삭제할 수 있습니다.

IFS='_' read -r -d '' -a array <<< "$r"
array[$((${#array[@]}-1))]=${array[$((${#array[@]}-1))]%?}

관련 정보