Я здивований, що ніхто не згадував очевидне bash
рішення, що використовує лише while
і read
.
while read -n1 character; do
echo "$character"
done < <(echo -n "$words")
Зверніть увагу на використання, echo -n
щоб уникнути сторонніх рядків в кінці. printf
є ще одним хорошим варіантом і може бути більш підходящим для ваших конкретних потреб. Якщо ви хочете ігнорувати пробіли, замініть "$words"
на "${words// /}"
.
Інший варіант fold
. Однак зауважте, що його ніколи не слід подавати у цикл for. Скоріше, використовуйте цикл while наступним чином:
while read char; do
echo "$char"
done < <(fold -w1 <<<"$words")
Основною перевагою використання зовнішньої fold
команди ( пакета coreutils ) буде стислість. Ви можете подати його вихід в іншу команду, таку як xargs
(частина пакета findutils ), наступним чином:
fold -w1 <<<"$words" | xargs -I% -- echo %
Вам потрібно буде замінити echo
команду, використану у наведеному вище прикладі, командою, яку потрібно виконати проти кожного символу. Зауважте, що xargs
пробіли за замовчуванням відкидаються. Ви можете -d '\n'
відключити таку поведінку.
Інтернаціоналізація
Я щойно перевірив fold
деякі азіатські символи і зрозумів, що він не підтримує Unicode. Тож, хоча це добре для потреб ASCII, це не буде працювати для всіх. У цьому випадку є кілька альтернатив.
Я б, мабуть, замінив fold -w1
масивом awk:
awk 'BEGIN{FS=""} {for (i=1;i<=NF;i++) print $i}'
Або grep
команда, згадана в іншій відповіді:
grep -o .
Продуктивність
FYI, я порівняв 3 вищезазначені варіанти. Перші два були швидкими, майже зв’язаними, причому петля згину була трохи швидшою, ніж петля while. Не дивно, що він xargs
був найповільнішим ... у 75 разів повільнішим.
Ось (скорочений) тест-код:
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
Ось результати:
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