web-dev-qa-db-ja.com

Bashスクリプト:各文字でWordを分割する

Wordの文字を分割し、各文字を別々の行に入れるにはどうすればよいですか?

たとえば、与えられた"StackOver" を見たいのですが

S
t
a
c
k
O
v
e
r

私はbashが初めてなので、どこから始めればよいかわかりません。

17
Sijaan Hallak

grepを使用します:

$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r

またはsed

$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r

そして、最後の空きスペースが問題である場合:

sed 's/\B/&\n/g' <<<"StackOver"

これらはすべて、GNU/Linuxを想定しています。

29
jimmij

テキストを垂直方向に印刷する場合は、文字ではなく書記素クラスタを分割することをお勧めします。たとえば、アキュートアクセントのあるeを使用します。

  • 書記素クラスターの場合(eとその鋭アクセントはone書記素クラスター):

    $ Perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
    S
    t
    é
    p
    h
    a
    n
    e
    

    (またはgrep -Po '\X' with GNU PCREサポートで構築されたgrep)

  • 文字あり(GNU grep)の場合):

    $ printf '%s\n' $'Ste\u301phane' | grep -o .
    S
    t
    e
    
    p
    h
    a
    n
    e
    
  • foldは文字を区切るためのものですが、GNU foldはマルチバイト文字をサポートしていないため、代わりにバイトで区切られます。

    $ printf '%s\n' $'Ste\u301phane' | fold -w 1
    S
    t
    e
    �
    �
    p
    h
    a
    n
    e
    

ASCII文字のみで構成されている(=文字ごとに1バイト、書記素クラスターごとに1文字)で構成されるStackOverでは、すべて3つでも同じ結果になります。

19

ボックスに Perl6 がある場合:

$ Perl6 -e 'for @*ARGS -> $w { .say for $w.comb }' 'cường'       
c
ư
ờ
n
g

ロケールに関係なく機能します。

6
cuonglm

多くのawkバージョン

awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
6
iruvar

具体的にはbashで回答を求めたので、これを純粋なbashで行う方法を次に示します。

while read -rn1; do echo "$REPLY" ; done <<< "StackOver"

これは " here document "の最後の改行をキャッチすることに注意してください。それを避けたいが、bashループで文字を繰り返し処理したい場合は、printfを使用して改行を避けます。

printf StackOver | while read -rn1; do echo "$REPLY" ; done
4
wyrm

fold (1) コマンドを使用できます。 grepおよびsedよりも効率的です。

$ time grep -o . <bigfile >/dev/null

real    0m3.868s
user    0m3.784s
sys     0m0.056s
$ time fold -b1 <bigfile >/dev/null

real    0m0.555s
user    0m0.528s
sys     0m0.016s
$

大きな違いの1つは、foldが空の行を出力で再現することです。

$ grep -o . <(printf "A\nB\n\nC\n\n\nD\n")
A
B
C
D
$ fold -b1 <(printf "A\nB\n\nC\n\n\nD\n")
A
B

C


D
$ 
4
joeytwiddle
echo StackOver | sed -e 's/./&\n/g'
S
t
a
c
k
O
v
e
r
4
henderson

以下は一般的なものです:

$ awk -F '' \
   'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>
4
user150073

また、 Python 2 はコマンドラインから使用できます。

python <<< "for x in 'StackOver':
   print x"

または:

echo "for x in 'StackOver':
    print x" | python

または(1_CRによるコメント付き) Python

python3 -c "print(*'StackOver',sep='\n')"
4
agold

次のようなマルチバイト文字を処理できます。

<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'

live入力を使用している場合は、バッファリングがなく、文字がwholeになるとすぐに出力されるため、これは非常に便利です。

3
mikeserv

ワード境界も使用できます。

$ Perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
3
Avinash Raj
s=stackoverflow;

$ time echo $s | fold -w1                                                                                                                                          
s                                                                                                                                                                          
t                                                                                                                                                                          
a                                                                                                                                                                          
c                                                                                                                                                                          
k                                                                                                                                                                          
o                                                                                                                                                                          
v
e
r

real    0m0.014s
user    0m0.000s
sys     0m0.004s

pdatesこれがハック|最速| pureBashBasedの方法です!

$ time eval eval printf \'%s\\\\n\' \\\${s:\{0..$((${#s}-1))}:1}
s
t
a
c
k
o
v
e
r

real    0m0.001s
user    0m0.000s
sys     0m0.000s

もっとすごい

function foldh () 
{ 
    if (($#)); then
        local s="$@";
        eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
    else
        while read s; do
            eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
        done;
    fi
}
function foldv () 
{ 
    if (($#)); then
        local s="$@";
        eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
    else
        while read s; do
            eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
        done;
    fi
}
1
Jonah

バッシュで:

これは任意のテキストとbash内部(外部ユーティリティは呼び出されない)でのみ機能するので、非常に短い文字列で高速になります。

str="Stéphane áàéèëêếe"

[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")

出力:

S
t
é
p
h
a
n
e

á
à
é
è
ë
ê
ế
e

IFSを変更し、位置パラメーターを変更してもよい場合は、サブシェル呼び出しを回避することもできます。

str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
set -- "${BASH_REMATCH[@]:1}"
IFS=$'\n'
echo "$*"
1
Isaac
for x in $(echo "$yourWordhere" | grep -o '.')
do
    code to perform operation on individual character $x of your Word
done
1
Chinmay Katil
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')

これでWordが分割され、配列varに格納されます。

1
Chinmay Katil