首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在bash shell中将一个字符串拆分成至少由一个空格分隔的多个字符串?

如何在bash shell中将一个字符串拆分成至少由一个空格分隔的多个字符串?
EN

Stack Overflow用户
提问于 2009-09-24 13:07:37
回答 11查看 466.2K关注 0票数 281

我有一个包含许多单词的字符串,每个单词之间至少有一个空格。如何将字符串拆分成单独的单词,以便循环遍历它们?

字符串作为参数传递。例如,${2} == "cat cat file"。我怎么才能遍历它?

另外,如何检查字符串是否包含空格?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2009-09-24 05:13:46

您是否尝试过将字符串变量传递给for循环?例如,Bash将自动拆分为空格。

代码语言:javascript
复制
sentence="This is   a sentence."
for word in $sentence
do
    echo $word
done
代码语言:javascript
复制
This
is
a
sentence.
票数 325
EN

Stack Overflow用户

发布于 2012-11-16 00:52:59

我喜欢转换为数组,以便能够访问单个元素:

代码语言:javascript
复制
sentence="this is a story"
stringarray=($sentence)

现在您可以直接访问单个元素(从0开始):

代码语言:javascript
复制
echo ${stringarray[0]}

或者转换回字符串以进行循环:

代码语言:javascript
复制
for i in "${stringarray[@]}"
do
  :
  # do whatever on $i
done

当然,前面已经回答了直接遍历字符串的问题,但这个答案的缺点是不能跟踪单个元素以供以后使用:

代码语言:javascript
复制
for i in $sentence
do
  :
  # do whatever on $i
done

另请参见Bash Array Reference

票数 362
EN

Stack Overflow用户

发布于 2015-05-13 18:44:22

在BASH 3和更高版本中,最简单和最安全的方法可能是:

代码语言:javascript
复制
var="string    to  split"
read -ra arr <<<"$var"

(其中arr是获取字符串拆分部分的数组),或者,如果输入中可能有换行符,并且您需要的不只是第一行:

代码语言:javascript
复制
var="string    to  split"
read -ra arr -d '' <<<"$var"

(请注意-d ''中的空格;不能省略它),但这可能会在<<<"$var"中给出一个意外的换行符(因为这会隐式地在末尾添加一个LF )。

示例:

代码语言:javascript
复制
touch NOPE
var="* a  *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done

输出预期的

代码语言:javascript
复制
[*]
[a]
[*]

因为这个解决方案(与这里的所有以前的解决方案不同)不容易出现意想不到的、通常是无法控制的外壳球状现象。

此外,这也为您提供了您可能想要的IFS的全部功能:

示例:

代码语言:javascript
复制
IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done

输出类似以下内容:

代码语言:javascript
复制
[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]

正如您所看到的,空格也可以通过这种方式保留:

代码语言:javascript
复制
IFS=: read -ra arr <<<' split  :   this    '
for a in "${arr[@]}"; do echo "[$a]"; done

输出

代码语言:javascript
复制
[ split  ]
[   this    ]

请注意,在BASH中对IFS的处理是一个独立的主题,因此您的测试也是如此;一些关于这方面的有趣主题:

  • unset IFS:忽略统计过程控制、制表符、NL和在线开始和ends
  • IFS='':的运行无字段分隔,仅读取统计过程控制(和仅限统计过程控制)的everything
  • IFS=' ':运行

最后的一些例子:

代码语言:javascript
复制
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

输出

代码语言:javascript
复制
1 [this is]
2 [a test]

代码语言:javascript
复制
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

输出

代码语言:javascript
复制
1 [this]
2 [is]
3 [a]
4 [test]

顺便说一句:

  • 如果你不习惯$'ANSI-ESCAPED-STRING',那就去习惯吧;这是一种省时的方法。

  • 如果不包含-r (就像在read -a arr <<<"$var"中一样),那么read会进行反斜杠转义。这是留给读者的练习。

关于第二个问题:

为了测试字符串中的内容,我通常坚持使用case,因为这样可以一次检查多个case (注意: case只执行第一个匹配,如果需要fallthrough,请使用多个case语句),这种需要通常就是这种情况(双关语):

代码语言:javascript
复制
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:

代码语言:javascript
复制
case "$var" in (*' '*) true;; (*) false;; esac

为什么是case?因为它通常比正则表达式序列更具可读性,而且多亏了Shell元字符,它可以很好地处理99%的所有需求。

票数 118
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1469849

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档