![仅使用 bash 将单个字符串拆分为字符数组](https://linux22.com/image/63360/%E4%BB%85%E4%BD%BF%E7%94%A8%20bash%20%E5%B0%86%E5%8D%95%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8B%86%E5%88%86%E4%B8%BA%E5%AD%97%E7%AC%A6%E6%95%B0%E7%BB%84.png)
我想仅使用 bash 分割'hello'
成h e l l o
一个数组,我可以在 sed 中执行此操作,sed 's/./& /g'
但我想知道当我不知道分隔符是什么或分隔符是什么时如何在 Bash 中将字符串分割成数组单个字符。我认为如果没有一些创造力,我就无法使用,${i// /}
因为分隔符是未知的,而且我认为该表达式不接受正则表达式。我尝试将 BASH_REMATCH 与 [[ string =~ ([az].).* ]] 一起使用,但它没有按我的预期工作。仅使用 bash 来完成某种string.split()
行为的正确方法是什么?原因是我试图在所有 bash 中编写 rev 实用程序:
while read data; do
word=($(echo $data|tr ' ' '_'|sed 's/./& /g'))
new=()
i=$((${#word[@]} - 1))
while [[ $i -ge 0 ]]; do
new+=(${word[$i]})
(( i-- ))
done
echo ${new[@]}|tr -d ' '|tr '_' ' '
done
但我使用了 tr 和 sed,我想知道如何正确地进行分割,然后我将其修复为全部 bash。只是为了好玩。
答案1
s="hello"
declare -a a # define array a
for ((i=0; i<${#s}; i++)); do a[$i]="${s:$i:1}"; done
declare -p a # print array a in a reusable form
输出:
声明 -aa='([0]="h" [1]="e" [2]="l" [3]="l" [4]="o")'
或(请注意评论)
s="hello"
while read -n 1 c; do a+=($c); done <<< "$s"
declare -p a
输出:
声明 -aa='([0]="h" [1]="e" [2]="l" [3]="l" [4]="o")'
答案2
要将字符串拆分为字符数组,使用空分隔符,您可以:
str='hello'
arr=()
i=0
while [ "$i" -lt "${#str}" ]; do
arr+=("${str:$i:1}")
i=$((i+1))
done
printf '%s\n' "${arr[@]}"
使用空以外的分隔符,您可以:
set -f
str='1,2,3,4,5'
IFS=',' arr=($str)
printf '%s\n' "${arr[@]}"
答案3
只是为了好玩(和其他 shell)其他变体:
word=hello
unset letter
while [ ${#word} -gt 0 ]
do
rest=${word#?}
letter[${#letter[*]}]=${word%$rest}
word=$rest
done
并检查
for l in "${!letter[@]}"
do
echo "letter [$l] = ${letter[l]}"
done
将打印
letter [0] = h
letter [1] = e
letter [2] = l
letter [3] = l
letter [4] = o
答案4
这是答案:https://stackoverflow.com/a/34634535/2332068
[[ "${text}" =~ ${text//?/(.)} ]] && array=("${BASH_REMATCH[@]:1}")
我在 bash 4.3 上使用了 ${data@Q} 的替代品
shell-escape-to() {
local REPLY="${*:2}"
[[ "${*:2}" =~ ${REPLY//?/(.)} ]] && printf -v "$1" "\\%c" "${BASH_REMATCH[@]:1}"
}
...
shell-escape-to dir_ "$dir"
sg "$GROUP" "exec mkdir -m 775 -p ${dir_}"
bash 4.4 及以上版本为: sg "$GROUP" "exec mkdir -m 775 -p ${dir@Q}"