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


17

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

たとえば、"StackOver" 私が見たいと思ったら

S
t
a
c
k
O
v
e
r

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

回答:


29

私は使用します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を想定しています。


grep -o。<<<¿¿¿.. -oは、提供されたパターンを正しく検索しますか?そして、それはあなたの命令でここで何をしますか?
シジャーンハッラク

1
@jimmij <<<が本当に何をするのかについての助けを見つけることができません!何か助け?
シジャーンハッラク

3
@SijaanHallakこれはいわゆるHere string、grosso modoと同等のecho foo | ...タイピングが少ないことと同じです。参照tldp.org/LDP/abs/html/x17837.html
jimmij

1
@SijaanHallak変更.する\B(ワード境界に一致していません)。
-jimmij

1
- @SijaanHallakあなたは、第二ドロップすることができますsedように:sed -et -e's/./\n&/g;//D'
mikeserv

19

テキストを垂直に印刷することが意図されている場合は、文字ではなく書記素クラスターを分割することができます。たとえばe、鋭アクセント付きのaの場合:

  • 書記素クラスターの場合(eその鋭いアクセントは1つの書記素クラスターになります):

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

    (またはgrep -Po '\X'PCREサポートでビルドされたGNU grepを使用)

  • 文字あり(ここではGNUありgrep):

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

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

StackOver ASCII文字のみで構成されています(文字あたり1バイト、書記素クラスタごとに1つの文字に)、すべての3つは同じ結果を与えるだろう。


私はgrep -Po、人が期待するようなことをしないことに驚いています(そうするようにgrep -P)。
-jimmij

@jimmij、どういう意味ですか?grep -Po .文字を検索し(改行文字に続く鋭角アクセントの組み合わせは無効です)、grep -Po '\X'graphemクラスタを検索します。それが正常に動作(またはしようとするためにあなたは、最近のgrepのバージョンおよび/またはPCREが必要な場合がありますgrep -Po '(*UTF8)\X'
ステファンChazelas

2
@SijaanHallakこれらは役に立つかもしれません:joelonsoftware.com/articles/Unicode.htmleev.ee/blog/2015/09/12/dark-corners-of-unicode
jpmc26

6

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

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

ロケールに関係なく動作します。


6

多くのawkバージョンで

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

すごい!しかし、nAWK( "One True AWK")の私のバージョンでは機能しません。しかし、これはトリックを実行します:(awk -v FS='' -v OFS='\n' '{$1=$1};1' それ-F ''がEREを生成する可能性があるので、それがより移植性があるかどうか疑問に思います//
eruve

4

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

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


4

特にbashで回答を求めたので、純粋なbashで回答する方法を次に示します。

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

これは、「ヒアドキュメント」の最後で改行をキャッチすることに注意してください。それを避けたいが、bashループで文字を繰り返し処理する場合はprintf、改行を避けるために使用します。

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

4

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

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

または:

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

または(1_CRのコメント通り)Python 3の場合

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

4

この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
$ 

3

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

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

あなたが作業しているときはかなり便利なことができ、ライブそこにはバッファリングはありませんし、すぐにそれがあるように、文字が印刷されるので、入力全体


NP、ロケールに関するメモを追加する必要がありますか?
クオンルム

StéphaneChazelasの回答のようなキャラクターを組み合わせた場合は機能しませんが、適切な正規化があれば問題になりません。
ケイは、

@Kay-必要に応じて文字を結合するために機能します-それsedがスクリプトの目的です。私は今についての1つを書く可能性はありません-私はかなり眠いです。しかし、端末を読むときは本当に便利です。
mikeserv

@cuonglm-必要に応じて。ただし、適切なlibcが指定されていれば、ロケールで機能するはずです。
mikeserv

ddマルチバイト文字が壊れるので、出力はテキストではなくなるので、sedの動作はPOSIXで規定されていないことに注意してください。
ステファンシャゼル16年


1

bashの場合:

これは任意のテキストで動作し、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
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

ここでの更新は、ハッキー|最速| 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
}

これにより、異なる結果が得られfold -b1ますか?
JigglyNaga

各バイトにはwidth = 1があるため、結果は同じになります!
ヨナ

1
では、これは以前の回答の複製でないのはどうしてですか?
JigglyNaga

これは、同じcmdが異なる引数で表示されるためです。
ジョナ


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