각 두 단어 사이에 하나 이상의 공백이있는 많은 단어가 포함 된 문자열이 있습니다. 문자열을 개별 단어로 분리하여 반복 할 수 있습니까?
문자열은 인수로 전달됩니다. 예 ${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 ]
IFS
BASH에서 의 처리는 자체 주제이므로 테스트와 관련하여 흥미로운 주제가 있습니다.
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"