Bạn cần xóa các ký tự khoảng trắng khỏi $IFStham số readđể dừng bỏ qua các ký tự đầu và cuối (với -n1ký tự khoảng trắng nếu có cả hai đầu và cuối, do đó bỏ qua):
while IFS= read -rn1 a; do printf %s "$a"; done
Nhưng ngay cả sau đó bash readsẽ bỏ qua các ký tự dòng mới, mà bạn có thể làm việc với:
while IFS= read -rn1 a; do printf %s "${a:-$'\n'}"; done
Mặc dù bạn có thể sử dụng IFS= read -d '' -rn1thay thế hoặc thậm chí tốt hơn IFS= read -N1(được thêm vào 4.1, được sao chép từ ksh93(thêm vào o)) là lệnh để đọc một ký tự.
Lưu ý rằng bash's readkhông thể đối phó với các ký tự NUL. Và ksh93 có vấn đề tương tự như bash.
Với zsh:
while read -ku0 a; do print -rn -- "$a"; done
(zsh có thể đối phó với các ký tự NUL).
Lưu ý rằng những người read -k/n/Nđọc một số ký tự , không phải byte . Vì vậy, đối với các ký tự đa nhân, họ có thể phải đọc nhiều byte cho đến khi một ký tự đầy đủ được đọc. Nếu đầu vào chứa các ký tự không hợp lệ, bạn có thể kết thúc bằng một biến chứa chuỗi byte không tạo thành các ký tự hợp lệ và lớp vỏ có thể sẽ được tính là nhiều ký tự . Ví dụ: trong miền địa phương UTF-8:
$ printf '\375\200\200\200\200ABC' | bash -c '
IFS= read -rN1 a; echo "${#a}"'
6
Điều đó \375sẽ giới thiệu một ký tự UTF-8 6 byte. Tuy nhiên, cái thứ 6 ( A) ở trên không hợp lệ cho ký tự UTF-8. Bạn vẫn kết thúc với \375\200\200\200\200Ain $a, được bashtính là 6 ký tự mặc dù 5 ký tự đầu tiên không thực sự là ký tự, chỉ có 5 byte không tạo thành một phần của bất kỳ ký tự nào.
IFSthành không có gì để có khoảng trắng tồn tại trong quá trình phân tách từ.