[bash] bash 쉘에서 하나의 문자열을 하나 이상의 공백으로 구분하여 여러 문자열로 나누는 방법은 무엇입니까?

각 두 단어 사이에 하나 이상의 공백이있는 많은 단어가 포함 된 문자열이 있습니다. 문자열을 개별 단어로 분리하여 반복 할 수 있습니까?

문자열은 인수로 전달됩니다. 예 ${2} == "cat cat file". 어떻게 반복 할 수 있습니까?

또한 문자열에 공백이 있는지 어떻게 확인할 수 있습니까?



답변

문자열 변수를 for루프에 전달하려고 했습니까 ? Bash는 공백으로 자동 분할됩니다.

sentence="This is   a sentence."
for word in $sentence
do
    echo $word
done

 

This
is
a
sentence.


답변

개별 요소에 액세스 할 수 있도록 배열로 변환하는 것이 좋습니다.

sentence="this is a story"
stringarray=($sentence)

이제 개별 요소에 직접 액세스 할 수 있습니다 (0으로 시작).

echo ${stringarray[0]}

또는 반복하기 위해 문자열로 다시 변환하십시오.

for i in "${stringarray[@]}"
do
  :
  # do whatever on $i
done

물론 문자열을 통한 루핑은 이전에 답변되었지만 그 대답은 나중에 사용하기 위해 개별 요소를 추적하지 않는 단점이있었습니다.

for i in $sentence
do
  :
  # do whatever on $i
done

Bash Array Reference참조하십시오 .


답변

쉘 “set”내장을 사용하십시오. 예를 들어

$ text 설정

그 후 $ text의 개별 단어는 $ 1, $ 2, $ 3 등이됩니다. 견고성을 위해 보통

세트-정크 $ 텍스트
시프트

$ text가 비어 있거나 대시로 시작하는 경우를 처리합니다. 예를 들면 다음과 같습니다.

text = "테스트입니다"
세트-정크 $ 텍스트
시프트
말을 위해; 하다
  에코 "[$ word]"
끝난

이것은 인쇄

[이]
[is]
[ㅏ]
[테스트]


답변

BASH 3 이상에서 가장 쉽고 안전한 방법은 다음과 같습니다.

var="string    to  split"
read -ra arr <<<"$var"

( arr문자열의 분할 된 부분을 취하는 배열입니다) 또는 입력에 줄 바꿈이 있고 첫 번째 줄 이상을 원할 경우 :

var="string    to  split"
read -ra arr -d '' <<<"$var"

(의 공간은 -d ''남겨 둘 수 없습니다.) 그러나 이것은 예기치 않은 줄 바꿈을 줄 수 있습니다 <<<"$var"(암시 적으로 끝에 LF를 추가하므로).

예:

touch NOPE
var="* a  *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done

예상 출력

[*]
[a]
[*]

이 솔루션은 (이전의 모든 솔루션과 달리) 예상치 못하고 종종 제어 할 수없는 쉘 글 로빙이되지 않습니다.

또한 이것은 원하는대로 IFS의 모든 기능을 제공합니다.

예:

IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done

다음과 같은 결과가 출력됩니다.

[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]

보시다시피, 공백도 이런 식으로 보존 될 수 있습니다 :

IFS=: read -ra arr <<<' split  :   this    '
for a in "${arr[@]}"; do echo "[$a]"; done

출력

[ split  ]
[   this    ]

IFSBASH에서 의 처리는 자체 주제이므로 테스트와 관련하여 흥미로운 주제가 있습니다.

  • unset IFS: SPC, TAB, NL의 실행을 무시하고 온라인 시작 및 종료
  • IFS='': 필드 분리가 필요 없으며 모든 것을 읽습니다.
  • IFS=' ': SPC 실행 (및 SPC 만 해당)

마지막 예

var=$'\n\nthis is\n\n\na test\n\n'
IFS=$'\n' read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done

출력

1 [this is]
2 [a test]

동안

unset IFS
var=$'\n\nthis is\n\n\na test\n\n'
read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done

출력

1 [this]
2 [is]
3 [a]
4 [test]

BTW :

  • 익숙하지 않으면 $'ANSI-ESCAPED-STRING'시간을 절약 할 수 있습니다.

  • 당신이 포함하지 않는 경우 -r(처럼 read -a arr <<<"$var")를 읽어 백 슬래시 이스케이프 않습니다. 이것은 독자의 연습으로 남아 있습니다.


두 번째 질문 :

문자열에서 무언가를 테스트하기 위해 case한 번에 여러 사례를 확인할 수 있으므로 일반적으로 고수합니다 (참고 : fallfall use multiplce case문이 필요한 경우 case는 첫 번째 일치 만 실행 ).이 경우는 종종 (pun 예정된):

case "$var" in
'')                empty_var;;                # variable is empty
*' '*)             have_space "$var";;        # have SPC
*[[:space:]]*)     have_whitespace "$var";;   # have whitespaces like TAB
*[^-+.,A-Za-z0-9]*) have_nonalnum "$var";;    # non-alphanum-chars found
*[-+.,]*)          have_punctuation "$var";;  # some punctuation chars found
*)                 default_case "$var";;      # if all above does not match
esac

따라서 다음과 같이 SPC를 확인하도록 반환 값을 설정할 수 있습니다.

case "$var" in (*' '*) true;; (*) false;; esac

case? 일반적으로 정규식 시퀀스보다 약간 읽기 쉽고 셸 메타 문자 덕분에 모든 요구의 99 %를 잘 처리합니다.


답변

$ echo "This is   a sentence." | tr -s " " "\012"
This
is
a
sentence.

공백을 확인하려면 grep을 사용하십시오.

$ echo "This is   a sentence." | grep " " > /dev/null
$ echo $?
0
$ echo "Thisisasentence." | grep " " > /dev/null
$ echo $?
1


답변

(A) 문장을 단어로 분리하려면 (공백으로 구분) 간단히 다음을 사용하여 기본 IFS를 사용할 수 있습니다

array=( $string )

다음 코드를 실행

#!/bin/bash

sentence="this is the \"sentence\"   'you' want to split"
words=( $sentence )

len="${#words[@]}"
echo "words counted: $len"

printf "%s\n" "${words[@]}" ## print array

출력합니다

words counted: 8
this
is
the
"sentence"
'you'
want
to
split

보시다시피 아무 문제없이 작은 따옴표 나 큰 따옴표도 사용할 수 있습니다

. 참고 :
-이것은 기본적으로 mob 의 대답 과 동일 하지만 더 필요한 경우 배열을 저장합니다. 단일 루프 만 필요한 경우 그의 대답을 사용할 수 있습니다. 한 줄이 더 짧습니다 🙂
– 구분 기호를 기준으로 문자열을 분할하는 다른 방법에 대해서는 이 질문 을 참조하십시오 .

(B) 문자열에서 문자를 확인하기 위해 정규식 일치를 사용할 수도 있습니다.
사용할 수있는 공백 문자가 있는지 확인하는 예 :

regex='\s{1,}'
if [[ "$sentence" =~ $regex ]]
    then
        echo "Space here!";
fi


답변

bash로 공간을 확인하려면 다음을 수행하십시오.

[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"