如何一个字符串分割成由bash shell中至少一个空格分隔的多个字符串?(How to split

2019-07-19 06:49发布

我有一个包含许多字与每两个之间的至少一个空间的字符串。 我如何分割字符串为单个单词这样我就可以通过他们循环?

该字符串作为参数传递。 例如, ${2} == "cat cat file" 。 如何通过它,我循环?

另外,我怎么能检查一个字符串包含空格?

Answer 1:

你尝试只是路过字符串变量的for循环? 击为一体,将自动分割上的空白。

sentence="This is   a sentence."
for word in $sentence
do
    echo $word
done

 

This
is
a
sentence.


Answer 2:

我喜欢转化成阵列,以便能够访问各个元素:

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

又见猛砸阵列参考 。



Answer 3:

只需使用炮弹“设置”内置。 例如,

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]


Answer 4:

在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%的非常好。



Answer 5:

$ 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


Answer 6:

(一)要分割句子的各个单词(空格隔开),你可以简单地通过使用默认的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


Answer 7:

对于检查只是bash的空间:

[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"


文章来源: How to split one string into multiple strings separated by at least one space in bash shell?