¿Cómo puedo dividir las letras de una palabra, con cada letra en una línea separada?
Por ejemplo, dado que "StackOver"
me gustaría ver
S
t
a
c
k
O
v
e
r
Soy nuevo en bash, así que no tengo idea de por dónde empezar.
¿Cómo puedo dividir las letras de una palabra, con cada letra en una línea separada?
Por ejemplo, dado que "StackOver"
me gustaría ver
S
t
a
c
k
O
v
e
r
Soy nuevo en bash, así que no tengo idea de por dónde empezar.
Respuestas:
Yo usaría grep
:
$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r
o sed
:
$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r
Y si el espacio vacío al final es un problema:
sed 's/\B/&\n/g' <<<"StackOver"
Todo eso suponiendo GNU / Linux.
Here string
grosso modo equivalente de echo foo | ...
escribir menos. Ver tldp.org/LDP/abs/html/x17837.html
.
a \B
(no coincide con el límite de la palabra).
sed
como:sed -et -e's/./\n&/g;//D'
Es posible que desee romper en grupos de grafemas en lugar de caracteres si la intención es imprimir texto verticalmente. Por ejemplo, con un e
acento agudo:
Con los grupos de grafemas ( e
con su acento agudo sería un grupo de grafemas):
$ perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
S
t
é
p
h
a
n
e
(o grep -Po '\X'
con GNU grep construido con soporte PCRE)
Con caracteres (aquí con GNU grep
):
$ printf '%s\n' $'Ste\u301phane' | grep -o .
S
t
e
p
h
a
n
e
fold
está destinado a dividir caracteres, pero GNU fold
no admite caracteres de varios bytes, por lo que se divide en bytes:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
En StackOver, que solo consta de caracteres ASCII (un byte por carácter, un carácter por grupo de grafemas), los tres darían el mismo resultado.
grep -Po
que no haga lo que uno esperaría (como grep -P
hace).
grep -Po .
encuentra caracteres (y un acento agudo combinado después de un carácter de nueva línea no es válido), y grep -Po '\X'
encuentra grupos de gráficos para mí. Es posible que necesite una versión reciente de grep y / o PCRE para que funcione correctamente (o intente grep -Po '(*UTF8)\X'
)
Con muchas awk
versiones
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
awk -v FS='' -v OFS='\n' '{$1=$1};1'
(preguntando si eso es más portátil, ya -F ''
que podría dar lugar al ERE: //
)
Lo siguiente 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 solicitó específicamente una respuesta en bash, aquí hay una manera de hacerlo en bash puro:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
Tenga en cuenta que esto capturará la nueva línea al final del " documento aquí ". Si desea evitar eso, pero aún itera sobre los caracteres con un bucle bash, use printf
para evitar la nueva línea.
printf StackOver | while read -rn1; do echo "$REPLY" ; done
Puedes usar el fold (1)
comando. Es más eficiente que grep
y 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
$
Una diferencia significativa es que el pliegue reproducirá líneas vacías en la salida:
$ 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
$
Puede manejar caracteres multibyte como:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
Lo que puede ser bastante útil cuando trabajas con entrada en vivo porque no hay almacenamiento en búfer allí y se imprime un personaje tan pronto como está completo .
sed
están los scripts. No es probable que escriba uno ahora mismo, tengo mucho sueño. Sin embargo, es realmente útil cuando se lee un terminal.
dd
romperá los caracteres multibyte, por lo que la salida ya no será texto, por lo que el comportamiento de sed no se especificará según POSIX.
También puede usar límites de palabras.
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
En bash:
Esto funciona con cualquier texto y solo con elementos internos de bash (no se llama una utilidad externa), por lo tanto, debe ser rápido en cadenas muy cortas.
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
Salida:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
Si está bien cambiar IFS y cambiar los parámetros posicionales, también puede evitar la llamada de 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
actualizaciones aquí es la manera hacky | rápido | 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 más genialidad
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
?
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')
esto dividirá su palabra y la almacenará en una matriz var
.
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done