Trong lập trình, việc phải đọc từng dòng trong một file để xử lý là điều vô cùng quen thuộc. Có thể lấy một vì dụ đơn giản về việc này đó là khi ta export được một danh sách các user trong hệ thống, sau đó ta cần xử lý với mỗi user thì tạo một thư mục web tương ứng. Lúc này ta nghĩ ngay đến việc sử dụng vòng lặp for….if hoặc while..do
Tuy nhiên khi nào dùng for..it khi nào dùng while….do thì ta cần xem một cách cụ thể như ví dụ sau
Giả sử ta có một file
$ cat /tmp/test.txt
Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR
Trong đó đáng chú ý:
Dưới đây là các phương thức để xử lý việc đọc ở từng dòng
1. Loại bỏ khoảng trắng ở đầu và cuối mỗi dòng
$ while read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
Như trên ta thấy, các khoảng trắng ở đầu (leading) và khoảng trắng ở cuối (trailing) cũng như dòng chứa ký tự CR đã bị loại bỏ. Nếu sử dụng IFS thay thế như sau:
while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
thì sẽ giữ đc leading và trailing nhưng vẫn bị mất dòng cuối chứa CR
2. Sử dụng cat để đọc toàn bộ file thay vì đọc từng dòng
$ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
'Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR'
Lúc này ta thấy toàn bộ 6 dòng trên chỉ còn ý nghĩa là 1 chuỗi duy nhất. Không đúng với yêu cầu lặp qua từng dòng một.
Nếu bỏ dấu ” ở $(cat /tmp/test.txt) đi thì mọi thứ còn tồi tệ hơn như sau:
'Line' '1' 'Line' '2' 'has' 'leading' 'space' 'Line' '3' 'followed' 'by' 'blank' 'line' 'Line' '5' '(follows' 'a' 'blank' 'line)' 'and' 'has' 'trailing' 'space' 'Line' '6' 'has' 'no' 'ending' 'CR'
3. Cách thức chuẩn nhất để đọc từng dòng và giữ nguyên nội dung của từng dòng đó, bất kể khoảng trắng hay ký tự xuống dòng đó là
$ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
' Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space '
'Line 6 has no ending CR'
Nếu muốn loại bỏ chỉ các ký tự trailing và leading thì chỉ cần bỏ IFS
$ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
'Line 6 has no ending CR'
Do đó có thể thấy, đôi khi for…if không phải là giải pháp tối ưu đối với những chuỗi mà có chứa khoảng trắng. Khi đó while..do là giải pháp tối ưu, nếu không muốn nói là duy nhất. Thuê VPS ở 1Hosting sẽ giúp quý khách tiết kiệm được nhiều thời gian với sự support của các kỹ sư hệ thống chuyên nghiệp. Còn chờ gì nữa, hãy nhấc máy và gọi Hotline 0915 54 99 22 để đăng ký vps và tận hưởng những công nghệ ưu việt nhất của chúng tôi. 1Hosting cam kết đem lại những giá trị tốt nhất cho tất cả các khách hàng đến với chúng tôi.
————————————————————
MỌI THÔNG TIN CHI TIẾT VUI LÒNG LIÊN HỆ
CÔNG TY CỔ PHẦN GIẢI PHÁP DỮ LIỆU TRỰC TUYẾN ANZ
Địa chỉ: Biệt thự 11 ngõ 233 đường Xuân Thủy, quận Cầu Giấy, Hà Nội
Email: info@1hosting.com.vn
Hotline: 0915 54 99 22