我有一个包含许多字与每两个之间的至少一个空间的字符串。 我如何分割字符串为单个单词这样我就可以通过他们循环?
该字符串作为参数传递。 例如, ${2} == "cat cat file"
。 如何通过它,我循环?
另外,我怎么能检查一个字符串包含空格?
我有一个包含许多字与每两个之间的至少一个空间的字符串。 我如何分割字符串为单个单词这样我就可以通过他们循环?
该字符串作为参数传递。 例如, ${2} == "cat cat file"
。 如何通过它,我循环?
另外,我怎么能检查一个字符串包含空格?
你尝试只是路过字符串变量的for
循环? 击为一体,将自动分割上的空白。
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
又见猛砸阵列参考 。
只需使用炮弹“设置”内置。 例如,
set $text
之后,在$文本中个别字词将在$ 1,$ 2,$ 3等。对于稳健性,人们通常不
set -- junk $text shift
处理其中$文本是空的情况下或以破折号开始。 例如:
text="This is a test" set -- junk $text shift for word; do echo "[$word]" done
这版画
[This] [is] [a] [test]
在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
,因为这样可以一次检查多个案件(注:情况下,只有执行的第一场比赛,如果你需要的下通使用multiplce case
报表),而这种需求是很常见的情况(双关语意):
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
? 因为它通常是一个位比正则表达式序列的可读性,并且由于shell字符它处理的所有需要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
(一)要分割句子的各个单词(空格隔开),你可以简单地通过使用默认的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
正如你可以看到你可以使用过单或双引号没有任何问题
笔记:
-这是基本相同的暴徒的答案,但这样你存储任何需要进一步的阵列。 如果你只需要一个循环,你可以用他的答案,这是一条线短:)
-请参考这个问题的替代方法来分割基于定界符的字符串。
(B)要检查字符的字符串,你也可以使用正则表达式匹配。
例如检查您可以使用空格字符的存在:
regex='\s{1,}'
if [[ "$sentence" =~ $regex ]]
then
echo "Space here!";
fi
对于检查只是bash的空间:
[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"