Comment puis-je diviser les lettres d'un mot, avec chaque lettre sur une ligne distincte?
Par exemple, étant donné "StackOver"
que j'aimerais voir
S
t
a
c
k
O
v
e
r
Je suis nouveau à bash donc je n'ai aucune idée par où commencer.
Comment puis-je diviser les lettres d'un mot, avec chaque lettre sur une ligne distincte?
Par exemple, étant donné "StackOver"
que j'aimerais voir
S
t
a
c
k
O
v
e
r
Je suis nouveau à bash donc je n'ai aucune idée par où commencer.
Réponses:
J'utiliserais 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
Et si l'espace vide à la fin est un problème:
sed 's/\B/&\n/g' <<<"StackOver"
Tout cela en supposant GNU / Linux.
Here string
, l'équivalent grosso modo d'un echo foo | ...
peu moins de frappe. Voir tldp.org/LDP/abs/html/x17837.html
.
à \B
(ne correspond pas sur une frontière de mot).
sed
comme:sed -et -e's/./\n&/g;//D'
Vous souhaiterez peut-être casser les grappes de graphèmes au lieu des caractères si l'intention est d'imprimer le texte verticalement. Par exemple avec un e
avec un accent aigu:
Avec des grappes de graphèmes ( e
avec son accent aigu serait un grappe de graphèmes):
$ perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
S
t
é
p
h
a
n
e
(ou grep -Po '\X'
avec GNU grep construit avec le support PCRE)
Avec des personnages (ici avec GNU grep
):
$ printf '%s\n' $'Ste\u301phane' | grep -o .
S
t
e
p
h
a
n
e
fold
est censé casser les caractères, mais GNU fold
ne prend pas en charge les caractères multi-octets, il se brise donc sur les octets à la place:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
Sur StackOver qui ne se compose que de caractères ASCII (donc un octet par caractère, un caractère par grappe de graphèmes), les trois donneraient le même résultat.
grep -Po
ne pas faire ce à quoi on pourrait s'attendre (comme le grep -P
fait).
grep -Po .
trouve des caractères (et un accent aigu combiné après un caractère de nouvelle ligne n'est pas valide) et grep -Po '\X'
trouve des grappes de graphes pour moi. Vous aurez peut-être besoin d'une version récente de grep et / ou PCRE pour qu'elle fonctionne correctement (ou essayez grep -Po '(*UTF8)\X'
)
Avec de nombreuses awk
versions
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
awk -v FS='' -v OFS='\n' '{$1=$1};1'
( se demandant si c'est plus facile à transporter car -F ''
pourrait donner l'ERE: //
)
Ce qui suit sera générique:
$ 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
Puisque vous avez spécifiquement demandé une réponse en bash, voici une façon de le faire en bash pur:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
Notez que cela interceptera la nouvelle ligne à la fin du " document ici ". Si vous voulez éviter cela, mais toujours parcourir les caractères avec une boucle bash, utilisez printf
pour éviter la nouvelle ligne.
printf StackOver | while read -rn1; do echo "$REPLY" ; done
Vous pouvez utiliser la fold (1)
commande. Il est plus efficace que grep
et 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
$
Une différence significative est que le pli reproduira les lignes vides dans la sortie:
$ 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
$
Vous pouvez gérer des caractères multi-octets comme:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
Ce qui peut être assez pratique lorsque vous travaillez avec une entrée en direct car il n'y a pas de mise en mémoire tampon et un caractère est imprimé dès qu'il est entier .
sed
servent les scripts. je ne suis pas susceptible d'en écrire un en ce moment - je suis assez endormi. il est cependant très utile lors de la lecture d'un terminal.
dd
cela cassera les caractères multi-octets, donc la sortie ne sera plus du texte donc le comportement de sed ne sera pas spécifié selon POSIX.
Vous pouvez également utiliser des limites de mots ..
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
En bash:
Cela fonctionne avec n'importe quel texte et avec uniquement des internes bash (aucun utilitaire externe appelé), donc, devrait être rapide sur des chaînes très courtes.
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
Production:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
S'il est correct de changer IFS et de changer les paramètres de position, vous pouvez également éviter l'appel de sous-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
mises à jour ici est la manière la plus rapide | 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
pour plus de génialité
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' ' ')
cela divisera votre mot et le stockera dans un tableau var
.
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done