bashのみを使用して単一の文字列を文字配列に分割する


9

私はbashのみを使用して配列に分割'hello'したいのですがh e l l o、sedでそれを行うことができますsed 's/./& /g'が、区切り文字が何であるかわからない場合、または区切り文字が任意の場合に、文字列をBashの配列に分割する方法を知りたいです単一の文字。${i// /}区切り文字が不明なため、ある程度の創造性がなければ使用できないと思います。また、式が正規表現を受け入れるとは思いません。[[string =〜([az]。)。*]]でBASH_REMATCHを使用してみましたが、期待どおりに動作しません。ある種string.split()の動作を達成するためにbashのみを使用する適切な方法は何ですか?その理由は、すべての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になるように修正します。楽しみのためだけに。


そのサイズを考えると、Stack Overflowにはサイト間の重複が必要です。候補の1つはBashです文字列を文字配列に分割します
Peter Mortensen

[[ $string =~ ${string//?/(.)} ]]BASH_REMATCH[]必要に応じて設定します。説明については、Peter Mortensenがリンクする質問への私の回答を参照してください。
mr.spuratic

回答:


12
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

出力:

declare -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

出力:

declare -aa = '([0] = "h" [1] = "e" [2] = "l" [3] = "l" [4] = "o")'

1
2つ目はいいですが、 "$ c"を引用符で囲まないため(この場合)のみ機能し、空白を削除して$ sの星を拡大します。
rici

2
2番目のオプションは次のとおり while read -N 1 c; do a+=("$c"); done <<< "$s"です。は-N改行まで読むことができ、引用符は("$c")パス名の展開(およびその他のいくつかの問題)を回避します。

1
もちろん、最後の改行を修正する必要がある場合は、次の行を変更しwhile read -N 1 c; do a+=("$c"); done <<< "$s"xますunset a[${#a[@]}-1]; unset a[${#a[@]}-1]。最後の改行と追加されたxを削除します 。

4

文字列をnull区切り文字で文字の配列に分割するには、次のことができます。

str='hello'
arr=()
i=0
while [ "$i" -lt "${#str}" ]; do
  arr+=("${str:$i:1}")
  i=$((i+1))
done

printf '%s\n' "${arr[@]}"

null以外の区切り文字を使用すると、次のことができます。

set -f
str='1,2,3,4,5'
IFS=',' arr=($str)
printf '%s\n' "${arr[@]}"

IFS設定できる場合は、次のようにしますIFS=',' arr=($str)
muru

2
@muru:その場合、グロブに行き詰まります。globを無効にして更新。
cuonglm 2015

@BinaryZebra:ああ、はい、私の悪い、行方不明の引用。修正しました、ありがとう。
cuonglm 2015

2

ちょうど楽しみのために(そして他のシェル)他のバリアント:

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

0

方法1:

一発ギャグ:

s="hello"
for ((i=0;i<${#s};i++)); do result[$i]="${s:i:1}"; done
echo ${result[@]}

拡張コード:

s="hello"                   # Original string.

for ((i=0;i<${#s};i++)); do # For i=0; i<(length of s); i++
    result[$i]="${s:i:1}"       # result[i] is equal to the i th character of $s
done                        # End of the loop

echo ${result[@]} # Print all elements of $result.

方法2:

一発ギャグ:

s="hello"
var=($(while read -n 1; do printf "$REPLY "; done <<< "$s"))
echo "${var[@]}"

拡張コード:

s="hello" # Original string.

while read -n 1; do # Read chraracter by character the string.
    space_separated=$(printf "$space_separated $REPLY") # $space_separated is equal to it plus the current character.
done <<< "$s" # Pass the string to the loop

result=($space_separated) # Split $space_separated into an array.

echo "${result[@]}" # Print all elements of $result.

提案による@cuonglmに感謝します。
効果的には、それが入力を読み取る$REPLYデフォルトの変数ですread


1
変数の$REPLY代わりに使用できcharます。
cuonglm 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.