Come posso dividere le lettere di una parola, con ciascuna lettera in una riga separata?
Ad esempio, dato "StackOver"
che vorrei vedere
S
t
a
c
k
O
v
e
r
Sono nuovo a bash quindi non ho idea di dove iniziare.
Come posso dividere le lettere di una parola, con ciascuna lettera in una riga separata?
Ad esempio, dato "StackOver"
che vorrei vedere
S
t
a
c
k
O
v
e
r
Sono nuovo a bash quindi non ho idea di dove iniziare.
Risposte:
Vorrei usare grep
:
$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r
oppure sed
:
$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r
E se lo spazio vuoto alla fine è un problema:
sed 's/\B/&\n/g' <<<"StackOver"
Tutto questo presupponendo GNU / Linux.
Here string
, grosso modo equivalente di echo foo | ...
appena meno battitura. Vedi tldp.org/LDP/abs/html/x17837.html
.
in \B
(non corrisponde al limite di parole).
sed
come:sed -et -e's/./\n&/g;//D'
È possibile che si desideri interrompere i grappoli anziché i caratteri se si intende stampare il testo in verticale. Ad esempio con una e
con un accento acuto:
Con i grappoli ( e
con il suo accento acuto sarebbe un grappolo):
$ 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 costruito con supporto PCRE)
Con personaggi (qui con GNU grep
):
$ printf '%s\n' $'Ste\u301phane' | grep -o .
S
t
e
p
h
a
n
e
fold
è pensato per rompere i caratteri, ma GNU fold
non supporta i caratteri multi-byte, quindi si rompe sui byte invece:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
Su StackOver che consiste solo di caratteri ASCII (quindi un byte per carattere, un carattere per cluster grapheme), tutti e tre darebbero lo stesso risultato.
grep -Po
che non faccia ciò che ci si aspetterebbe (come grep -P
fa).
grep -Po .
trova i caratteri (e un accento acuto combinato che segue un carattere di nuova riga non è valido) e grep -Po '\X'
trova graphem grappoli per me. Potrebbe essere necessaria una versione recente di grep e / o PCRE per funzionare correttamente (o provare grep -Po '(*UTF8)\X'
)
Con molte awk
versioni
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
awk -v FS='' -v OFS='\n' '{$1=$1};1'
(chiedo se questo è più portabile in quanto -F ''
potrebbe cedere l'ERE: //
)
Di seguito sarà generico:
$ 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
Dato che hai specificamente chiesto una risposta in bash, ecco un modo per farlo in puro bash:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
Si noti che questo prenderà la nuova riga alla fine del " documento qui ". Se vuoi evitarlo, ma continua a scorrere i personaggi con un ciclo bash, usa printf
per evitare la nuova riga.
printf StackOver | while read -rn1; do echo "$REPLY" ; done
Puoi usare il fold (1)
comando È più efficiente di 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
$
Una differenza significativa è che fold riprodurrà righe vuote nell'output:
$ 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
$
Puoi gestire caratteri multibyte come:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
Il che può essere molto utile quando lavori con input live perché non c'è buffering lì e un personaggio viene stampato non appena è intero .
sed
gli script sono per. probabilmente non ne scriverò uno proprio ora - sono piuttosto assonnato. è molto utile, tuttavia, quando si legge un terminale.
dd
interromperà i caratteri multibyte, quindi l'output non sarà più testo, quindi il comportamento di sed non sarà specificato secondo POSIX.
Puoi usare anche i confini delle parole.
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
In bash:
Funziona con qualsiasi testo e con solo interni bash (nessuna utility esterna chiamata), quindi dovrebbe essere veloce su stringhe molto brevi.
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
Produzione:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
Se è possibile modificare IFS e modificare i parametri posizionali, è anche possibile evitare la chiamata della shell secondaria:
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
gli aggiornamenti qui sono il modo più veloce e veloce |
$ 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
per più suggestione
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' ' ')
questo dividerà la tua parola e la memorizzerà nella matrice var
.
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done