如何拆分一个单词的字母,每个字母都分开一行?
例如,鉴于"StackOver"
我希望看到
S
t
a
c
k
O
v
e
r
我是bash的新手,所以我不知道从哪里开始。
如何拆分一个单词的字母,每个字母都分开一行?
例如,鉴于"StackOver"
我希望看到
S
t
a
c
k
O
v
e
r
我是bash的新手,所以我不知道从哪里开始。
Answers:
我会用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。
.
为\B
(在单词边界上不匹配)。
sed
喜欢的东西:sed -et -e's/./\n&/g;//D'
如果要垂直打印文本,则可能要中断字素簇而不是字符。例如带有e
重音符号的:
对于字素簇(e
带有重音符号的将是一个字素簇):
$ 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
本意是要打破字符,但是GNU fold
不支持多字节字符,因此它就打破了字节:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
上 仅由ASCII字符组成的StackOver上(因此,每个字符一个字节,每个字素簇一个字符),所有这三个将给出相同的结果。
grep -Po
没有像人们期望的那样grep -P
做。
grep -Po .
查找字符(并且在换行符后合并尖音符号无效),并grep -Po '\X'
为我查找字素簇。您可能需要一个最近grep和/或PCRE的版本才能正常工作(或尝试grep -Po '(*UTF8)\X'
)
您可以使用该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
$
一个重要的区别是,折叠将在输出中重现空行:
$ 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
$
您可以处理多字节字符,例如:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
当你正在使用它可以非常方便的实时输入,因为没有缓冲那里,打印字符尽快它是整体。
sed
脚本的用途。我现在不太可能写一个-我很困。但是,在阅读终端时它确实很有用。
dd
将破坏多字节字符,因此输出将不再是文本,因此根据POSIX,未指定sed的行为。
您也可以使用单词边界。
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
在bash中:
这适用于任何文本,并且仅适用于bash内部(不调用外部实用程序),因此,在非常短的字符串上应该很快。
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
输出:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
如果可以更改IFS和更改位置参数,也可以避免子shell调用:
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
set -- "${BASH_REMATCH[@]:1}"
IFS=$'\n'
echo "$*"
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
这里更新是hacky | fastest | 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
吗?