각 두 단어 사이에 하나 이상의 공백이있는 많은 단어가 포함 된 문자열이 있습니다. 문자열을 개별 단어로 분리하여 반복 할 수 있습니까?
문자열은 인수로 전달됩니다. 예 ${2} == "cat cat file"
. 어떻게 반복 할 수 있습니까?
또한 문자열에 공백이 있는지 어떻게 확인할 수 있습니까?
각 두 단어 사이에 하나 이상의 공백이있는 많은 단어가 포함 된 문자열이 있습니다. 문자열을 개별 단어로 분리하여 반복 할 수 있습니까?
문자열은 인수로 전달됩니다. 예 ${2} == "cat cat file"
. 어떻게 반복 할 수 있습니까?
또한 문자열에 공백이 있는지 어떻게 확인할 수 있습니까?
답변:
문자열 변수를 for
루프에 전달하려고 했습니까 ? Bash는 공백으로 자동 분할됩니다.
sentence="This is a sentence."
for word in $sentence
do
echo $word
done
This
is
a
sentence.
A=${A}${word})
.
touch NOPE; var='* a *'; for a in $var; do echo "[$a]"; done
출력 (LF는 가독성을 위해 SPC로 대체 됨). [NOPE] [a] [NOPE]
[*] [a] [*]
개별 요소에 액세스 할 수 있도록 배열로 변환하는 것이 좋습니다.
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
touch NOPE; var='* a *'; arr=($var); set | grep ^arr=
출력arr=([0]="NOPE" [1]="a" [2]="NOPE")
arr=([0]="*" [1]="a" [2]="*")
쉘 "set"내장을 사용하십시오. 예를 들어
$ text 설정
그 후 $ text의 개별 단어는 $ 1, $ 2, $ 3 등이됩니다. 견고성을 위해 보통
세트-정크 $ 텍스트 시프트
$ text가 비어 있거나 대시로 시작하는 경우를 처리합니다. 예를 들면 다음과 같습니다.
text = "테스트입니다" 세트-정크 $ 텍스트 시프트 말을 위해; 하다 에코 "[$ word]" 끝난
이것은 인쇄
[이] [is] [ㅏ] [테스트]
awk
했지만 set
훨씬 쉽습니다. 나는 지금 set
팬보이입니다. 감사합니다 @Idelic!
touch NOPE; var='* a *'; set -- $var; for a; do echo "[$a]"; done
출력 . 분할 된 문자열에 SHELL 메타 문자가 없음을 101 % 확신하는 경우에만 사용하십시오! [NOPE] [a] [NOPE]
[*] [a] [*]
set -f
이전 set -- $var
과 set +f
이후에 해제 대체 (globbing)에.
set -f
솔루션도 안전합니다. 그러나 set +f
각 쉘의 기본값이므로 필수 세부 사항입니다. 다른 사람들도 아마 그것을 알지 못하기 때문에 주목해야합니다.
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 %를 잘 처리합니다.
set -f
하거나 set -o noglob
전환 할 수 있습니다 . 그러나 나는 쉘의 많은 힘을 남기고 /이 설정을 전환하는 것이 매우 오류가 많기 때문에 실제로 그 친구는 아닙니다.
;&
이를 달성 할 수 있습니다 . 어떤 버전의 bash가 있는지 확실하지 않습니다. 저는 4.3 사용자입니다
;;&
D 감사합니다, 그리고 쉘은 당신과 함께있을 수 있습니다) : 당신이 주석 전에
$ 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
echo "X" |
일반적으로 다음 <<<"X"
과 같이 로 대체 할 수 있습니다 grep -s " " <<<"This contains SPC"
. 과 echo X | read var
달리 무언가를하면 차이를 발견 할 수 있습니다 read var <<< X
. 후자는 변수 var
를 현재 쉘로 가져 오지만 첫 번째 변형에서 변수 에 액세스하려면 다음과 같이 그룹화해야합니다.echo X | { read var; handle "$var"; }
(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