Ich bin überrascht, dass niemand die offensichtliche bash
Lösung erwähnt hat, die nur while
und verwendet read
.
while read -n1 character; do
echo "$character"
done < <(echo -n "$words")
Beachten Sie die Verwendung von echo -n
, um die überflüssige neue Zeile am Ende zu vermeiden. printf
ist eine weitere gute Option und möglicherweise besser für Ihre speziellen Bedürfnisse geeignet. Wenn Sie Leerzeichen ignorieren möchten, ersetzen Sie diese "$words"
durch "${words// /}"
.
Eine andere Option ist fold
. Bitte beachten Sie jedoch, dass es niemals in eine for-Schleife eingespeist werden sollte. Verwenden Sie stattdessen eine while-Schleife wie folgt:
while read char; do
echo "$char"
done < <(fold -w1 <<<"$words")
Der Hauptvorteil der Verwendung des externen fold
Befehls (des Coreutils- Pakets) wäre die Kürze. Sie können die Ausgabe wie folgt einem anderen Befehl wie xargs
(Teil des findutils- Pakets) zuführen :
fold -w1 <<<"$words" | xargs -I% -- echo %
Sie möchten den echo
im obigen Beispiel verwendeten Befehl durch den Befehl ersetzen, den Sie für jedes Zeichen ausführen möchten . Beachten Sie, dass xargs
Leerzeichen standardmäßig verworfen werden. Sie können -d '\n'
dieses Verhalten deaktivieren.
Internationalisierung
Ich habe gerade fold
mit einigen asiatischen Charakteren getestet und festgestellt, dass es keine Unicode-Unterstützung gibt. Obwohl es für ASCII-Anforderungen in Ordnung ist, funktioniert es nicht für alle. In diesem Fall gibt es einige Alternativen.
Ich würde wahrscheinlich durch fold -w1
ein awk-Array ersetzen :
awk 'BEGIN{FS=""} {for (i=1;i<=NF;i++) print $i}'
Oder der grep
in einer anderen Antwort erwähnte Befehl:
grep -o .
Performance
Zu Ihrer Information, ich habe die 3 oben genannten Optionen verglichen. Die ersten beiden waren schnell und fast gebunden, wobei die Faltschleife etwas schneller war als die while-Schleife. Es überrascht nicht, dass xargs
es am langsamsten war ... 75x langsamer.
Hier ist der (abgekürzte) Testcode:
words=$(python -c 'from string import ascii_letters as l; print(l * 100)')
testrunner(){
for test in test_while_loop test_fold_loop test_fold_xargs test_awk_loop test_grep_loop; do
echo "$test"
(time for (( i=1; i<$((${1:-100} + 1)); i++ )); do "$test"; done >/dev/null) 2>&1 | sed '/^$/d'
echo
done
}
testrunner 100
Hier sind die Ergebnisse:
test_while_loop
real 0m5.821s
user 0m5.322s
sys 0m0.526s
test_fold_loop
real 0m6.051s
user 0m5.260s
sys 0m0.822s
test_fold_xargs
real 7m13.444s
user 0m24.531s
sys 6m44.704s
test_awk_loop
real 0m6.507s
user 0m5.858s
sys 0m0.788s
test_grep_loop
real 0m6.179s
user 0m5.409s
sys 0m0.921s