上猛砸符串分割,分配段阵列 [英] Bash split string on delimiter, assign segments to array
问题描述
在庆典,我想改变一个路径般的环境变量的可能的包含空格隔开的元素到阵列
,使的确定的元素承载空间做不会导致字分裂,表现为多元素。
让 PATH_VARIABLE
是有问题的变量。
让取消:dodecaedro:每:tirare:每:我丹妮
是变量的内容
的是的意 所需的阵列
_to有无 6
元素,不是 7
。
0)UN
1)dodecaedro
2)每
3)tirare
4)每
5)我丹妮
在刁钻条目可能是空间分隔值:我丹妮
我要寻找绝对的最优雅的和正确的方式来实现这一目标。
局限性:它必须与我的庆典版本: v3.2.48(1)-release
在蟒蛇这样做只是美丽的像这样:
>>> V ='联合国:dodecaedro:每:tirare:每:我丹妮
>>> LEN(v.split(':'))
6
作品。显示了我所期待的。
什么是做在我们敬爱的庆典的最佳方式?
你能明确我尝试改善 4
?
在这里,我尝试
#!/斌/庆典PATH_VARIABLE ='UN:dodecaedro:每:tirare:每:我丹妮#错误
A1 =($(回声$ PATH_VARIABLE | TR':'的'\\ n'))#错误
A2 =($(
而读path_component;做
回声$ path_component
完成< ≤(回声$ PATH_VARIABLE| TR':'的'\\ n')
))#工程,它是优雅..但我没有庆典4!
#readarray -t A3< ≤(回声$ PATH_VARIABLE| TR':'的'\\ n')#作品,但它看起来笨重给我:(
I = 0
而读线;做
A4 [我++] = $行
完成< ≤(回声$ PATH_VARIABLE| TR':'的'\\ n')N = $ {#A4 [@]}
为((i = 0; I< N;我++));做
printf的'%2D)%S \\ n'$ I$ {A4 [I]}
DONE
我的环境
庆典 v3.2.48(1) - 发布
OSX OS X v10.8.3(建12D78)
F(){
当地IFS =:
当地富
设置-f#禁止水珠扩张
富=($ @)#故意不带引号
集+ F
printf的%d个\\ N'$ {#foo的[@]}
printf的'%s的\\ n'$ {foo的[@]}
}F'UN:dodecaedro:每:tirare:每:我丹妮
6
联合国
dodecaedro
每
tirare
每
我丹妮
修改吉姆·麦克纳马拉的答案,你可以只重置IFS:
oIFS =$ IFS
富='联合国:dodecaedro:每:tirare:每:我丹妮
IFS =:ARR =($富)
IFS =$ oIFS
我preFER功能范围,因为它保护IFS变化从出血到全球范围,而不需要特殊照顾重置。
编辑和解释:
作为澄清的问题:在第二个例子中,IFS设置的确实的改变全局变量。这之间的差异显着:
IFS =:ARR =($富)
和这样的:
IFS =:读-a ARR<<< $富
是,前者是两个可变分配,没有命令,而后者的一个简单的命令的(见的简单的命令的在男人(1 )庆典
)
演示:
$回声$ BASH_VERSION
3.2.48(1)-release
$回声$ IFS
$ foo的='UN:dodecaedro:每:tirare:每:我丹妮
$ IFS =:读-a ARR<<< $富
$回声$ {#ARR [@]}
6
$回声$ IFS
$ IFS =:ARR1 =($富)
$回声$ {#ARR1 [@]}
6
$回声$ IFS
:
In bash, I would like to transform a PATH-like environment variable that may contain space-separated elements into an array
, making sure elements bearing spaces do not cause word-splitting, appearing as "multiple elements".
Let PATH_VARIABLE
be the variable in question.
Let un:dodecaedro:per:tirare:per:i danni
be the content of the variable.
It is intended for the desired array
_to have 6
elements, not 7
.
0) un
1) dodecaedro
2) per
3) tirare
4) per
5) i danni
The "tricky" entry may be the space-separated value: i danni
.
I am looking for the absolute most elegant and correct way to achieve this.
Limitation: it must work with my bash version: v3.2.48(1)-release
In python this is done just beautifully as so:
>>> v='un:dodecaedro:per:tirare:per:i danni'
>>> len(v.split(':'))
6
Works. Shows what I am looking for.
What's the best way to do this in our beloved bash?
Can you specifically improve on my attempt 4
?
Here my attempts
#!/bin/bash
PATH_VARIABLE='un:dodecaedro:per:tirare:per:i danni'
# WRONG
a1=($(echo $PATH_VARIABLE | tr ':' '\n'))
# WRONG
a2=($(
while read path_component; do
echo "$path_component"
done < <(echo "$PATH_VARIABLE" | tr ':' '\n')
))
# WORKS, it is elegant.. but I have no bash 4!
# readarray -t a3 < <(echo "$PATH_VARIABLE" | tr ':' '\n')
# WORKS, but it looks "clunky" to me :(
i=0
while read line; do
a4[i++]=$line
done < <(echo "$PATH_VARIABLE" | tr ':' '\n')
n=${#a4[@]}
for ((i=0; i < n; i++)); do
printf '%2d) %s\n' "$i" "${a4[i]}"
done
My environment
bash v3.2.48(1)-release
osx OS X v10.8.3 (build 12D78)
f() {
local IFS=:
local foo
set -f # Disable glob expansion
foo=( $@ ) # Deliberately unquoted
set +f
printf '%d\n' "${#foo[@]}"
printf '%s\n' "${foo[@]}"
}
f 'un:dodecaedro:per:tirare:per:i danni'
6
un
dodecaedro
per
tirare
per
i danni
Modifying Jim McNamara's answer, you could just reset IFS:
oIFS="$IFS"
foo='un:dodecaedro:per:tirare:per:i danni'
IFS=: arr=( $foo )
IFS="$oIFS"
I prefer the function scope because it protects IFS changes from bleeding into the global scope without requiring special care to reset it.
Edits and explanations:
As a matter of clarification: In the second example, the IFS setting does change the global variable. The salient difference between this:
IFS=: arr=( $foo )
and this:
IFS=: read -a arr <<< "$foo"
is that the former is two variable assignments and no commands, and the latter is a simple command (see simple command in man (1) bash
.)
Demonstration:
$ echo "$BASH_VERSION"
3.2.48(1)-release
$ echo "$IFS"
$ foo='un:dodecaedro:per:tirare:per:i danni'
$ IFS=: read -a arr <<< "$foo"
$ echo "${#arr[@]}"
6
$ echo "$IFS"
$ IFS=: arr1=( $foo )
$ echo "${#arr1[@]}"
6
$ echo "$IFS"
:
这篇关于上猛砸符串分割,分配段阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!