我有一个包含许多单词的字符串,每个单词之间至少有一个空格。如何将字符串拆分成单独的单词,以便循环遍历它们?
字符串作为参数传递。例如,${2} == "cat cat file"。我怎么才能遍历它?
另外,如何检查字符串是否包含空格?
发布于 2009-09-24 05:13:46
您是否尝试过将字符串变量传递给for循环?例如,Bash将自动拆分为空格。
sentence="This is a sentence."
for word in $sentence
do
echo $word
doneThis
is
a
sentence.发布于 2012-11-16 00:52:59
我喜欢转换为数组,以便能够访问单个元素:
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。
发布于 2015-05-13 18:44:22
在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 ]请注意,在BASH中对IFS的处理是一个独立的主题,因此您的测试也是如此;一些关于这方面的有趣主题:
unset IFS:忽略统计过程控制、制表符、NL和在线开始和endsIFS='':的运行无字段分隔,仅读取统计过程控制(和仅限统计过程控制)的everythingIFS=' ':运行最后的一些例子:
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]顺便说一句:
$'ANSI-ESCAPED-STRING',那就去习惯吧;这是一种省时的方法。-r (就像在read -a arr <<<"$var"中一样),那么read会进行反斜杠转义。这是留给读者的练习。关于第二个问题:
为了测试字符串中的内容,我通常坚持使用case,因为这样可以一次检查多个case (注意: case只执行第一个匹配,如果需要fallthrough,请使用多个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%的所有需求。
https://stackoverflow.com/questions/1469849
复制相似问题