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"
(where arr
is the array which takes the splitted parts of the string) or, if there might be newlines in the input and you want more than just the first line:
var="string to split"
read -ra arr -d '' <<<"$var"
(please note the space in -d ''
, it cannot be left away), but this might give you an unexpected newline from <<<"$var"
(as this implicitly adds an LF at the end).
Example:
touch NOPE
var="* a *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done
Outputs the expected
[*]
[a]
[*]
as this solution (in contrast to all previous solutions here) is not prone to unexpected and often uncontrollable shell globbing.
Also this gives you the full power of IFS as you probably want:
Example:
IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done
Outputs something like:
[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]
As you can see, spaces can be preserved this way, too:
IFS=: read -ra arr <<<' split : this '
for a in "${arr[@]}"; do echo "[$a]"; done
outputs
[ split ]
[ this ]
Please note that the handling of IFS
in BASH is a subject on it's own, so do your tests, some interesting topics on this:
unset IFS
: Ignores runs of SPC, TAB, NL and on line starts and endsIFS=''
: No field separation, just reads everythingIFS=' '
: Runs of SPC (and SPC only)
Some last example
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
outputs
1 [this is]
2 [a test]
while
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
outputs
1 [this]
2 [is]
3 [a]
4 [test]
BTW:
If you are not used to
$'ANSI-ESCAPED-STRING'
get used to it, it's a timesaver.If you do not include
-r
(like inread -a arr <<<"$var"
) then read does backslash escapes. This is left as exercise for the reader.
For the second question:
To test for something in a string I usually stick to case
, as this can check for multiple cases at once (note: case only executes the first match, if you need fallthrough use multiplce case
statements), and this need is quite often the case (pun intended):
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
So you can set the return value to check for SPC like this:
case "$var" in (*' '*) true;; (*) false;; esac
Why case
? Because it usually is a bit more readable than regex sequences, and thanks to Shell metacharacters it handles 99% of all needs very well.
$ echo "This is a sentence." | tr -s " " "\012"
This
is
a
sentence.
For checking for spaces, use grep:
$ echo "This is a sentence." | grep " " > /dev/null
$ echo $?
0
$ echo "Thisisasentence." | grep " " > /dev/null
$ echo $?
1
(A) To split a sentence into its words (space separated) you can simply use the default IFS by using
array=( $string )
Example running the following snippet
#!/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
will output
words counted: 8
this
is
the
"sentence"
'you'
want
to
split
As you can see you can use single or double quotes too without any problem
Notes:
-- this is basically the same of mob's answer, but in this way you store the array for any further needing. If you only need a single loop, you can use his answer, which is one line shorter :)
-- please refer to this question for alternate methods to split a string based on delimiter.
(B) To check for a character in a string you can also use a regular expression match.
Example to check for the presence of a space character you can use:
regex='\s{1,}'
if [[ "$sentence" =~ $regex ]]
then
echo "Space here!";
fi
For checking spaces just with bash:
[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"
'Programing' 카테고리의 다른 글
의도를 통해 열거 또는 객체 전달 (최상의 솔루션) (0) | 2020.05.08 |
---|---|
Node.js에서 Mongoose로 페이지 매김하는 방법? (0) | 2020.05.08 |
ASP.NET 웹 양식에 Runat =“Server”속성이 필요한 이유는 무엇입니까? (0) | 2020.05.08 |
작업 표시 줄 탐색 모드는 Android L에서 더 이상 사용되지 않습니다. (0) | 2020.05.08 |
jQuery 템플릿 엔진 (0) | 2020.05.08 |