Tôi ngạc nhiên là không ai đề cập đến bash
giải pháp rõ ràng chỉ sử dụng while
và read
.
while read -n1 character; do
echo "$character"
done < <(echo -n "$words")
Lưu ý sử dụng echo -n
để tránh dòng mới không liên quan ở cuối. printf
là một lựa chọn tốt khác và có thể phù hợp hơn cho các nhu cầu cụ thể của bạn. Nếu bạn muốn bỏ qua khoảng trắng thì hãy thay thế "$words"
bằng "${words// /}"
.
Một lựa chọn khác là fold
. Tuy nhiên, xin lưu ý rằng nó không bao giờ được đưa vào vòng lặp for. Thay vào đó, hãy sử dụng một vòng lặp while như sau:
while read char; do
echo "$char"
done < <(fold -w1 <<<"$words")
Lợi ích chính của việc sử dụng fold
lệnh bên ngoài (của gói coreutils ) sẽ là ngắn gọn. Bạn có thể cung cấp đầu ra của nó cho một lệnh khác chẳng hạn như xargs
(một phần của gói findutils ) như sau:
fold -w1 <<<"$words" | xargs -I% -- echo %
Bạn sẽ muốn thay thế echo
lệnh được sử dụng trong ví dụ trên bằng lệnh bạn muốn chạy với từng ký tự. Lưu ý rằng xargs
sẽ loại bỏ khoảng trắng theo mặc định. Bạn có thể sử dụng -d '\n'
để vô hiệu hóa hành vi đó.
Quốc tế hóa
Tôi vừa thử nghiệm fold
với một số ký tự châu Á và nhận ra rằng nó không hỗ trợ Unicode. Vì vậy, mặc dù nó là tốt cho nhu cầu ASCII, nó sẽ không hoạt động cho tất cả mọi người. Trong trường hợp đó, có một số lựa chọn thay thế.
Tôi có thể thay thế fold -w1
bằng một mảng awk:
awk 'BEGIN{FS=""} {for (i=1;i<=NF;i++) print $i}'
Hoặc grep
lệnh được đề cập trong một câu trả lời khác:
grep -o .
Hiệu suất
FYI, tôi đã đánh giá tiêu chuẩn cho 3 tùy chọn nói trên. Hai lần đầu tiên nhanh, gần như buộc lại, với vòng lặp gấp nhanh hơn một chút so với vòng lặp while. Không có gì đáng ngạc nhiên xargs
là tốc độ chậm nhất ... chậm hơn 75 lần.
Đây là mã kiểm tra (viết tắt):
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
Đây là kết quả:
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