string 如何在bash shell中将一个字符串拆分为由至少一个空格分隔的多个字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1469849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to split one string into multiple strings separated by at least one space in bash shell?
提问by derrdji
I have a string containing many words with at least one space between each two. How can I split the string into individual words so I can loop through them?
我有一个包含许多单词的字符串,每两个单词之间至少有一个空格。如何将字符串拆分为单个单词,以便循环遍历它们?
The string is passed as an argument. E.g. ${2} == "cat cat file"
. How can I loop through it?
该字符串作为参数传递。例如${2} == "cat cat file"
。我怎样才能遍历它?
Also, how can I check if a string contains spaces?
另外,如何检查字符串是否包含空格?
回答by Highwind
I like the conversion to an array, to be able to access individual elements:
我喜欢转换为数组,以便能够访问单个元素:
sentence="this is a story"
stringarray=($sentence)
now you can access individual elements directly (it starts with 0):
现在您可以直接访问单个元素(以 0 开头):
echo ${stringarray[0]}
or convert back to string in order to loop:
或转换回字符串以循环:
for i in "${stringarray[@]}"
do
:
# do whatever on $i
done
Of course looping through the string directly was answered before, but that answer had the the disadvantage to not keep track of the individual elements for later use:
当然,之前已经回答了直接遍历字符串,但该回答的缺点是无法跟踪各个元素以供以后使用:
for i in $sentence
do
:
# do whatever on $i
done
See also Bash Array Reference.
另请参阅Bash 数组参考。
回答by mob
Did you try just passing the string variable to a for
loop? Bash, for one, will split on whitespace automatically.
您是否尝试将字符串变量传递给for
循环?一方面,Bash 将自动在空白处拆分。
sentence="This is a sentence."
for word in $sentence
do
echo $word
done
This
is
a
sentence.
回答by Idelic
Just use the shells "set" built-in. For example,
只需使用内置的shell“set”即可。例如,
set $text
After that, individual words in $text will be in $1, $2, $3, etc. For robustness, one usually does
之后,$text 中的单个单词将在 $1、$2、$3 等中。为了健壮性,通常会这样做
set -- junk $text shift
to handle the case where $text is empty or start with a dash. For example:
处理 $text 为空或以破折号开头的情况。例如:
text="This is a test" set -- junk $text shift for word; do echo "[$word]" done
This prints
这打印
[This] [is] [a] [test]
回答by Tino
The probably most easy and most secure way in BASH 3 and above 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:
(其中arr
采用字符串拆分部分的数组在哪里)或者,如果输入中可能有换行符并且您想要的不仅仅是第一行:
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).
(请注意 中的空格-d ''
,它不能被遗漏),但这可能会给你一个意想不到的换行符<<<"$var"
(因为这在最后隐含地添加了一个 LF)。
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.
因为此解决方案(与此处的所有先前解决方案相比)不容易出现意外且通常无法控制的 shell globbing。
Also this gives you the full power of IFS as you probably want:
这也为您提供了 IFS 的全部功能,如您所愿:
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:
请注意,IFS
在 BASH中的处理本身就是一个主题,所以你的测试也是如此,一些有趣的主题是:
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)
unset IFS
:忽略 SPC、TAB、NL 和在线开始和结束的运行IFS=''
: 没有字段分离,只是读取所有内容IFS=' '
:运行 SPC(仅限 SPC)
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.
如果你
$'ANSI-ESCAPED-STRING'
不习惯它,它会节省时间。如果您不包括
-r
(如 inread -a arr <<<"$var"
),则 read 会进行反斜杠转义。这留给读者作为练习。
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
,因为这可以一次检查多个案例(注意:案例仅执行第一个匹配,如果您需要失败,请使用 multiplcecase
语句),并且这种情况经常发生(双关语)故意的):
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:
因此,您可以设置返回值来检查 SPC,如下所示:
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.
为什么case
?因为它通常比正则表达式序列更具可读性,而且由于 Shell 元字符,它可以很好地处理 99% 的所有需求。
回答by DVK
$ echo "This is a sentence." | tr -s " " "2"
This
is
a
sentence.
For checking for spaces, use grep:
要检查空格,请使用 grep:
$ echo "This is a sentence." | grep " " > /dev/null
$ echo $?
0
$ echo "Thisisasentence." | grep " " > /dev/null
$ echo $?
1
回答by Luca Borrione
(A)To split a sentence into its words (space separated) you can simply use the default IFS by using
(A)要将句子拆分为单词(空格分隔),您只需使用默认的 IFS 即可
array=( $string )
Examplerunning 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 questionfor 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:
正如您所看到的,您也可以使用单引号或双引号而不会出现任何问题
注意:
-- 这与mob的答案基本相同,但是通过这种方式您可以存储数组以供进一步需要。如果您只需要一个循环,您可以使用他的答案,它缩短了一行 :)
-- 请参阅此问题以了解基于分隔符拆分字符串的替代方法。
(B)要检查字符串中的字符,您还可以使用正则表达式匹配。
检查是否存在可以使用的空格字符的示例:
regex='\s{1,}'
if [[ "$sentence" =~ $regex ]]
then
echo "Space here!";
fi
回答by glenn Hymanman
For checking spaces just with bash:
只用 bash 来检查空格:
[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"
回答by álex
echo $WORDS | xargs -n1 echo
This outputs every word, you can process that list as you see fit afterwards.
这会输出每个单词,之后您可以根据需要处理该列表。