Como posso dividir as letras de uma palavra, com cada letra em uma linha separada?
Por exemplo, dado que "StackOver"
eu gostaria de ver
S
t
a
c
k
O
v
e
r
Eu sou novo no bash, então não tenho idéia por onde começar.
Como posso dividir as letras de uma palavra, com cada letra em uma linha separada?
Por exemplo, dado que "StackOver"
eu gostaria de ver
S
t
a
c
k
O
v
e
r
Eu sou novo no bash, então não tenho idéia por onde começar.
Respostas:
Eu usaria grep
:
$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r
ou sed
:
$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r
E se o espaço vazio no final for um problema:
sed 's/\B/&\n/g' <<<"StackOver"
Tudo isso assumindo o GNU / Linux.
Here string
, grosso modo equivalente a echo foo | ...
apenas menos digitação. Veja tldp.org/LDP/abs/html/x17837.html
.
para \B
(não corresponde ao limite da palavra).
sed
como:sed -et -e's/./\n&/g;//D'
Convém quebrar os clusters de grafema em vez de caracteres, se a intenção for imprimir texto verticalmente. Por exemplo, com um e
sotaque agudo:
Com clusters de grafema ( e
com seu sotaque agudo seria um cluster de grafema):
$ perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
S
t
é
p
h
a
n
e
(ou grep -Po '\X'
com o GNU grep criado com suporte para PCRE)
Com caracteres (aqui com GNU grep
):
$ printf '%s\n' $'Ste\u301phane' | grep -o .
S
t
e
p
h
a
n
e
fold
destina-se a quebrar caracteres, mas o GNU fold
não suporta caracteres de bytes múltiplos; portanto, quebra em bytes:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
No StackOver, que consiste apenas em caracteres ASCII (portanto, um byte por caractere, um caractere por cluster de grafema), os três forneceriam o mesmo resultado.
grep -Po
que não faça o que se esperaria (como grep -P
faz).
grep -Po .
encontra caracteres (e um sotaque agudo combinado após um caractere de nova linha é inválido) e grep -Po '\X'
encontra grupos de graphem para mim. Você pode precisar de uma versão recente do grep e / ou PCRE para que ele funcione corretamente (ou tentar grep -Po '(*UTF8)\X'
)
Com muitas awk
versões
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
awk -v FS='' -v OFS='\n' '{$1=$1};1'
(perguntando se isso é mais portátil já que -F ''
pode produzir o ERE: //
)
O abaixo será genérico:
$ awk -F '' \
'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>
echo StackOver | sed -e 's/./&\n/g'
S
t
a
c
k
O
v
e
r
Como você pediu especificamente uma resposta no bash, eis uma maneira de fazê-lo no bash puro:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
Observe que isso capturará a nova linha no final do " documento aqui ". Se você quiser evitar isso, mas ainda repetir os caracteres com um loop bash, use printf
para evitar a nova linha.
printf StackOver | while read -rn1; do echo "$REPLY" ; done
Você pode usar o fold (1)
comando É mais eficiente que grep
e 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
$
Uma diferença significativa é que a dobra reproduzirá linhas vazias na saída:
$ 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
$
Você pode manipular caracteres multibyte como:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
O que pode ser bastante útil quando você estiver trabalhando com entrada ao vivo, porque não há buffer e um caractere é impresso assim que ele é inteiro .
sed
servem os scripts. Não é provável que eu escreva uma sobre isso agora - estou com muito sono. é realmente útil, porém, ao ler um terminal.
dd
isso quebrará caracteres multibyte, portanto a saída não será mais texto, portanto o comportamento do sed não será especificado conforme POSIX.
Você também pode usar limites de palavras.
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
Na festança:
Isso funciona com qualquer texto e apenas com internos do bash (nenhum utilitário externo chamado), portanto, deve ser rápido em seqüências muito curtas.
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
Resultado:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
Se estiver correto alterar o IFS e alterar os parâmetros posicionais, você também pode evitar a chamada sub 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
atualizações aqui é a maneira hacky | mais rápida | 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
para mais grandiosidade
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
}
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')
isso dividirá sua palavra e a armazenará em matriz var
.
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done