web-dev-qa-db-ja.com

Bashの文字列内の各文字に対してforループを実行する方法は?

このような変数があります:

words="这是一条狗。"

私は、各キャラクターにforループを一度に1つずつ作成したいと思います。最初 character="这"、次にcharacter="是"character="一"など.

私が知っている唯一の方法は、ファイル内の各行を区切るために各文字を出力し、while read line、しかしこれは非常に非効率的だ。

  • Forループを使用して文字列の各文字を処理するにはどうすればよいですか?
63
Village

LANG=en_US.UTF-8sed Shellでdashを使用すると、次のことが正しく機能します。

$ echo "你好嗎 新年好。全型句號" | sed -e 's/\(.\)/\1\n/g'
你
好
嗎

新
年
好
。
全
型
句
號

そして

$ echo "Hello world" | sed -e 's/\(.\)/\1\n/g'
H
e
l
l
o

w
o
r
l
d

したがって、出力はwhile read ... ; do ... ; doneでループできます。

サンプルテキストを編集して英語に翻訳する:

"你好嗎 新年好。全型句號" is zh_TW.UTF-8 encoding for:
"你好嗎"     = How are you[ doing]
" "         = a normal space character
"新年好"     = Happy new year
"。全型空格" = a double-byte-sized full-stop followed by text description
38
Rony

Cスタイルのforループを使用できます。

foo=string
for (( i=0; i<${#foo}; i++ )); do
  echo "${foo:$i:1}"
done

${#foo}fooの長さに拡張されます。 ${foo:$i:1}は、長さ1の$i位置から始まる部分文字列に展開されます。

195
chepner

${#var}varの長さを返します

${var:pos:N}pos以降からN文字を返します

例:

$ words="abc"
$ echo ${words:0:1}
a
$ echo ${words:1:1}
b
$ echo ${words:2:1}
c

繰り返しが簡単です。

別の方法:

$ grep -o . <<< "abc"
a
b
c

または

$ grep -o . <<< "abc" | while read letter;  do echo "my letter is $letter" ; done 

my letter is a
my letter is b
my letter is c
28
Tiago Peczenyj

これはアスキー文字列でのみテストしましたが、次のようなことができます:

while test -n "$words"; do
   c=${words:0:1}     # Get the first character
   echo character is "'$c'"
   words=${words:1}   # trim the first character
done
13
William Pursell

foldを使用して文字列を文字配列に分割し、この配列を反復処理することもできます。

for char in `echo "这是一条狗。" | fold -w1`; do
    echo $char
done
5
sebix

@chepnerの答えのCスタイルのループは、シェル関数update_terminal_cwd、 そしてその grep -o .ソリューションは賢明ですが、seqを使用したソリューションが表示されないことに驚きました。これが私のものです:

read Word
for i in $(seq 1 ${#Word}); do
  echo "${Word:i-1:1}"
done
4
De Novo

空白が無視されることを気にしない場合の別のアプローチ:

for char in $(sed -E s/'(.)'/'\1 '/g <<<"$your_string"); do
    # Handle $char here
done
0
anon

別の方法は次のとおりです。

Characters="TESTING"
index=1
while [ $index -le ${#Characters} ]
do
    echo ${Characters} | cut -c${index}-${index}
    index=$(expr $index + 1)
done
0
Javier Salas