use*_*001 8 unix linux bash shell
我正在寻找一种方法来将bash中的字符串拆分为分隔符字符串,并将这些部分放在一个数组中.
简单案例:
#!/bin/bash
b="aaaaa/bbbbb/ddd/ffffff"
echo "simple string: $b"
IFS='/' b_split=($b)
echo ;
echo "split"
for i in ${b_split[@]}
do
echo "------ new part ------"
echo "$i"
done
Run Code Online (Sandbox Code Playgroud)
给出输出
simple string: aaaaa/bbbbb/ddd/ffffff
split
------ new part ------
aaaaa
------ new part ------
bbbbb
------ new part ------
ddd
------ new part ------
ffffff
Run Code Online (Sandbox Code Playgroud)
更复杂的情况:
#!/bin/bash
c=$(echo "AA=A"; echo "B=BB"; echo "======="; echo "C==CC"; echo "DD=D"; echo "======="; echo "EEE"; echo "FF";)
echo "more complex string"
echo "$c";
echo ;
echo "split";
IFS='=======' c_split=($c) ;# <---- LINE TO BE CHANGED
for i in ${c_split[@]}
do
echo "------ new part ------"
echo "$i"
done
Run Code Online (Sandbox Code Playgroud)
给出输出:
more complex string
AA=A
B=BB
=======
C==CC
DD=D
=======
EEE
FF
split
------ new part ------
AA
------ new part ------
A
B
------ new part ------
BB
------ new part ------
------ new part ------
------ new part ------
------ new part ------
------ new part ------
------ new part ------
------ new part ------
C
------ new part ------
------ new part ------
CC
DD
------ new part ------
D
------ new part ------
------ new part ------
------ new part ------
------ new part ------
------ new part ------
------ new part ------
------ new part ------
EEE
FF
Run Code Online (Sandbox Code Playgroud)
我想第二个输出就像
------ new part ------
AA=A
B=BB
------ new part ------
C==CC
DD=D
------ new part ------
EEE
FF
Run Code Online (Sandbox Code Playgroud)
即将字符串拆分为一系列字符,而不是一个字符.我怎样才能做到这一点?
我正在寻找一个只会在第二个脚本中修改此行的答案:
IFS='=======' c_split=($c) ;# <---- LINE TO BE CHANGED
Run Code Online (Sandbox Code Playgroud)
F. *_*uri 18
IFS 消歧IFS意思是输入字段分隔符,如list of characters that could be used as separators.
默认情况下,此设置为 \t\n,表示任何数字(大于零)的空格,制表 和/或 换行符可以是一个 separator.
所以字符串:
" blah foo=bar
baz "
Run Code Online (Sandbox Code Playgroud)
开头和结尾的分隔符会被忽略,这个字符串将只包含3个部分:blah,foo=bar和baz.
IFS如果您知道字符串中未使用的有效字段分隔符,则可以使用拆分字符串.
OIFS="$IFS"
IFS='§'
c=$'AA=A\nB=BB\n=======\nC==CC\nDD=D\n=======\nEEE\nFF'
c_split=(${c//=======/§})
IFS="$OIFS"
printf -- "------ new part ------\n%s\n" "${c_split[@]}"
------ new part ------
AA=A
B=BB
------ new part ------
C==CC
DD=D
------ new part ------
EEE
FF
Run Code Online (Sandbox Code Playgroud)
但这只在字符串不包含时才起作用§.
你可以使用另一个角色,IFS=$'\026';c_split=(${c//=======/$'\026'})但无论如何这可能涉及到更多的错误.
您可以浏览角色地图以查找不在您的字符串中的人:
myIfs=""
for i in {1..255};do
printf -v char "$(printf "\\\%03o" $i)"
[ "$c" == "${c#*$char}" ] && myIfs="$char" && break
done
if ! [ "$myIFS" ] ;then
echo no split char found, could not do the job, sorry.
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
但我发现这个解决方案有点矫枉过正.
在bash下,我们可以使用这个基础:
b="aaaaa/bbbbb/ddd/ffffff"
b_split=(${b//// })
Run Code Online (Sandbox Code Playgroud)
事实上,这syntaxe ${varname//将启动转换(由分隔/替换出现的所有)/一个空格, before assigning it to an array b_split.
当然,这仍然IFS在空间上使用和拆分数组.
这不是最好的方法,但可以适用于特定情况.
您甚至可以在拆分之前删除不需要的空格:
b='12 34 / 1 3 5 7 / ab'
b1=${b// }
b_split=(${b1//// })
printf "<%s>, " "${b_split[@]}" ;echo
<12>, <34>, <1>, <3>, <5>, <7>, <ab>,
Run Code Online (Sandbox Code Playgroud)
或交换他们......
b1=${b// /§}
b_split=(${b1//// })
printf "<%s>, " "${b_split[@]//§/ }" ;echo
<12 34 >, < 1 3 5 7 >, < ab>,
Run Code Online (Sandbox Code Playgroud)
strings:所以,你必须不使用IFS你的意思,但是bash中确实有很好的功能:
#!/bin/bash
c=$'AA=A\nB=BB\n=======\nC==CC\nDD=D\n=======\nEEE\nFF'
echo "more complex string"
echo "$c";
echo ;
echo "split";
mySep='======='
while [ "$c" != "${c#*$mySep}" ];do
echo "------ new part ------"
echo "${c%%$mySep*}"
c="${c#*$mySep}"
done
echo "------ last part ------"
echo "$c"
Run Code Online (Sandbox Code Playgroud)
让我们看看:
more complex string
AA=A
B=BB
=======
C==CC
DD=D
=======
EEE
FF
split
------ new part ------
AA=A
B=BB
------ new part ------
C==CC
DD=D
------ last part ------
EEE
FF
Run Code Online (Sandbox Code Playgroud)
注意:不删除前导和尾随换行符.如果需要,您可以:
mySep=$'\n=======\n'
Run Code Online (Sandbox Code Playgroud)
而不是简单的=======.
或者你可以重写split循环来明确地保持这个:
mySep=$'======='
while [ "$c" != "${c#*$mySep}" ];do
echo "------ new part ------"
part="${c%%$mySep*}"
part="${part##$'\n'}"
echo "${part%%$'\n'}"
c="${c#*$mySep}"
done
echo "------ last part ------"
c=${c##$'\n'}
echo "${c%%$'\n'}"
Run Code Online (Sandbox Code Playgroud)
无论如何,这个匹配的问题是什么(和他的样本:)
------ new part ------
AA=A
B=BB
------ new part ------
C==CC
DD=D
------ last part ------
EEE
FF
Run Code Online (Sandbox Code Playgroud)
array#!/bin/bash
c=$'AA=A\nB=BB\n=======\nC==CC\nDD=D\n=======\nEEE\nFF'
echo "more complex string"
echo "$c";
echo ;
echo "split";
mySep=$'======='
export -a c_split
while [ "$c" != "${c#*$mySep}" ];do
part="${c%%$mySep*}"
part="${part##$'\n'}"
c_split+=("${part%%$'\n'}")
c="${c#*$mySep}"
done
c=${c##$'\n'}
c_split+=("${c%%$'\n'}")
for i in "${c_split[@]}"
do
echo "------ new part ------"
echo "$i"
done
Run Code Online (Sandbox Code Playgroud)
这样做很好:
more complex string
AA=A
B=BB
=======
C==CC
DD=D
=======
EEE
FF
split
------ new part ------
AA=A
B=BB
------ new part ------
C==CC
DD=D
------ new part ------
EEE
FF
Run Code Online (Sandbox Code Playgroud)
export -a var定义var为数组并在子项中共享它们${variablename%string*},${variablename%%string*}导致variablename的左侧部分,upto但没有字符串.一个%意思是字符串的最后一个实例,并%%为所有出现.返回完整的variablename是找不到字符串.${variablename#*string},以相反的方式执行相同的操作:返回变量名的最后一部分但不使用字符串.一个#意思是第一次出现两个##人所有出现.Nota替换,角色*是一个小丑,意味着任何数字的任何角色.
该命令echo "${c%%$'\n'}"将回显变量c但在字符串末尾没有任何数量的换行符.
所以如果变量包含Hello WorldZorGluBHello youZorGluBI'm happy,
variable="Hello WorldZorGluBHello youZorGluBI'm happy"
$ echo ${variable#*ZorGluB}
Hello youZorGlubI'm happy
$ echo ${variable##*ZorGluB}
I'm happy
$ echo ${variable%ZorGluB*}
Hello WorldZorGluBHello you
$ echo ${variable%%ZorGluB*}
Hello World
$ echo ${variable%%ZorGluB}
Hello WorldZorGluBHello youZorGluBI'm happy
$ echo ${variable%happy}
Hello WorldZorGluBHello youZorGluBI'm
$ echo ${variable##* }
happy
Run Code Online (Sandbox Code Playgroud)
所有这些都在联机帮助页中解释:
$ man -Len -Pless\ +/##word bash
$ man -Len -Pless\ +/%%word bash
$ man -Len -Pless\ +/^\\\ *export\\\ .*word bash
Run Code Online (Sandbox Code Playgroud)
分隔符:
mySep=$'======='
Run Code Online (Sandbox Code Playgroud)
声明c_split为数组(并且可以与子项共享)
export -a c_split
Run Code Online (Sandbox Code Playgroud)
变量c确实包含至少一个出现的mySep
while [ "$c" != "${c#*$mySep}" ];do
Run Code Online (Sandbox Code Playgroud)
TRUNC Ç从第一mySep结束字符串和指定给part.
part="${c%%$mySep*}"
Run Code Online (Sandbox Code Playgroud)
删除主要换行符
part="${part##$'\n'}"
Run Code Online (Sandbox Code Playgroud)
删除尾随换行符并将结果添加为新的数组元素c_split.
c_split+=("${part%%$'\n'}")
Run Code Online (Sandbox Code Playgroud)
Reassing ç蒙山字符串的其余高达离开时mySep被删除
c="${c#*$mySep}"
Run Code Online (Sandbox Code Playgroud)
完成;-)
done
Run Code Online (Sandbox Code Playgroud)
删除主要换行符
c=${c##$'\n'}
Run Code Online (Sandbox Code Playgroud)
删除尾随换行符并将结果添加为新的数组元素c_split.
c_split+=("${c%%$'\n'}")
Run Code Online (Sandbox Code Playgroud)
ssplit() {
local string="$1" array=${2:-ssplited_array} delim="${3:- }" pos=0
while [ "$string" != "${string#*$delim}" ];do
printf -v $array[pos++] "%s" "${string%%$delim*}"
string="${string#*$delim}"
done
printf -v $array[pos] "%s" "$string"
}
Run Code Online (Sandbox Code Playgroud)
用法:
ssplit "<quoted string>" [array name] [delimiter string]
Run Code Online (Sandbox Code Playgroud)
其中阵列名称是$splitted_array默认和分隔符是一个单一的空间.
你可以使用:
c=$'AA=A\nB=BB\n=======\nC==CC\nDD=D\n=======\nEEE\nFF'
ssplit "$c" c_split $'\n=======\n'
printf -- "--- part ----\n%s\n" "${c_split[@]}"
--- part ----
AA=A
B=BB
--- part ----
C==CC
DD=D
--- part ----
EEE
FF
Run Code Online (Sandbox Code Playgroud)