Wordの文字を分割し、各文字を別々の行に入れるにはどうすればよいですか?
たとえば、与えられた"StackOver"
を見たいのですが
S
t
a
c
k
O
v
e
r
私はbashが初めてなので、どこから始めればよいかわかりません。
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を想定しています。
テキストを垂直方向に印刷する場合は、文字ではなく書記素クラスタを分割することをお勧めします。たとえば、アキュートアクセントのある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つでも同じ結果になります。
ボックスに Perl6 がある場合:
$ Perl6 -e 'for @*ARGS -> $w { .say for $w.comb }' 'cường'
c
ư
ờ
n
g
ロケールに関係なく機能します。
多くのawk
バージョン
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
具体的にはbashで回答を求めたので、これを純粋なbashで行う方法を次に示します。
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
これは " here document "の最後の改行をキャッチすることに注意してください。それを避けたいが、bashループで文字を繰り返し処理したい場合は、printf
を使用して改行を避けます。
printf StackOver | while read -rn1; do echo "$REPLY" ; done
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
$
echo StackOver | sed -e 's/./&\n/g'
S
t
a
c
k
O
v
e
r
以下は一般的なものです:
$ awk -F '' \
'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>
次のようなマルチバイト文字を処理できます。
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
live入力を使用している場合は、バッファリングがなく、文字がwholeになるとすぐに出力されるため、これは非常に便利です。
ワード境界も使用できます。
$ Perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
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
}
バッシュで:
これは任意のテキストと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 "$*"
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your Word
done
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')
これでWordが分割され、配列var
に格納されます。