2013-09-08 44 views
5

Đây là file.txt:Bash: Sự khác biệt giữa mèo và tiếng vang

foo:bar:baz:qux:quux 
one:two:tree:four:five:six:seven 
alpha:beta:gamma:delta:epsilon:zeta:eta:teta:iota:kappa:lambda:mu 
the quick brown fox jumps over the lazy dog 

Đây là những gì tôi đã cố gắng trong terminal:

[email protected]:~/Desktop$ cat file.txt 
foo:bar:baz:qux:quux 
one:two:tree:four:five:six:seven 
alpha:beta:gamma:delta:epsilon:zeta:eta:teta:iota:kappa:lambda:mu 
the quick brown fox jumps over the lazy [email protected]:~/Desktop$ cat read.sh 
while read -r line 
do 
    echo $line 
done < file.txt 

[email protected]:~/Desktop$ ./read.sh 
foo:bar:baz:qux:quux 
one:two:tree:four:five:six:seven 
alpha:beta:gamma:delta:epsilon:zeta:eta:teta:iota:kappa:lambda:mu 

Câu hỏi của tôi là: tại sao không read.sh hiển thị cuối cùng cuối dòng như cat file.txt?

Trả lời

6

Vì không có cuối dòng trong file.txt, nếu bạn:

$ od -c file.txt 
0000000 f o o : b a r : b a z : q u x : 
0000020 q u u x \n o n e : t w o : t r e 
0000040 e : f o u r : f i v e : s i x : 
0000060 s e v e n \n a l p h a : b e t a 
0000100 : g a m m a : d e l t a : e p s 
0000120 i l o n : z e t a : e t a : t e 
0000140 t a : i o t a : k a p p a : l a 
0000160 m b d a : m u \n t h e  q u i c 
0000200 k  b r o w n  f o x  j u m p 
0000220 s  o v e r  t h e  l a z y  
0000240 d o g 

Không có \n vào cuối của tập tin.

echo mặt khác sẽ luôn thêm dòng mới khi bạn lặp lại thư nếu không có thư.

+0

'wc -l' là một cách hay để xác nhận điều này. Vì vậy, là 'od -ta', để hiển thị vị trí các ký tự dòng mới. – Joe

+1

@ Joe wc -l không hoàn toàn đúng để phát hiện điều này: nó cho thấy 3 nếu không có đào tạo \ n - 'od -c' là một cách hay để xác nhận nếu có \ n - cảm ơn cho mẹo. –

1

Tệp nhập của bạn không kết thúc bằng dòng mới.

cat file chỉ cần sao chép nội dung tệp vào đầu ra tiêu chuẩn. Nó hoạt động theo các ký tự, không phải các dòng, vì vậy nó không quan tâm nếu tập tin kết thúc bằng một dòng mới hay không. Nhưng nếu nó không kết thúc bằng một dòng mới, nó sẽ không thêm một vào đầu ra.

read -r line sẽ đọc một dòng vào biến. Nó sẽ chỉ báo cáo thành công nếu dòng kết thúc bằng một dòng mới. Nếu dòng cuối cùng của đầu vào không kết thúc bằng dòng mới, nó sẽ báo cáo một lỗi, như thể đã đạt được EOF. Vì vậy, vòng lặp kết thúc khi nó cố gắng đọc dòng cuối cùng, thay vì trả lại dòng đó. Đó là lý do tại sao tập lệnh không bao giờ hiển thị dòng bắt đầu bằng the quick brown fox.

Nói chung, các chương trình tệp văn bản Unix chỉ được xác định để hoạt động trên các tệp văn bản kết thúc bằng dòng mới. Điều trị của họ về dòng cuối cùng nếu nó không có một dòng mới thường không được chỉ định.

+0

Tôi chưa bao giờ thực sự xem xét nội dung của biến khi 'đọc' trả về lỗi, vì vậy tôi đã không nhận ra sự khác biệt. Tôi đã cập nhật câu trả lời của mình. – Barmar

0

file.txt của bạn không chứa dòng mới ở cuối dòng cuối cùng. Do đó cat không hiển thị.

Lưu ý rằng read.sh không hiển thị dòng cuối cùng ... trong read.sh, read đang chờ dòng đầu vào hoàn chỉnh và do dòng cuối cùng không bị ngắt bởi dòng mới, vì vậy nó không thực sự được đọc.

4

Câu trả lời khác là đúng, chỉ đơn giản là không có ký tự dòng mới ở cuối số file.txt của bạn.

Hầu hết các trình chỉnh sửa văn bản sẽ tự động kết thúc tệp với một dòng mới, ngay cả nano thực hiện điều đó. Nhưng tệp của bạn đã được tạo bởi tập lệnh, phải không? Để tái tạo hành vi này tất cả các bạn phải làm là:

echo -n 'hello world' >> file.txt 

-n cờ nói vang không để sản xuất các newline trailing.

Ngoài ra, nếu bạn muốn mã read của bạn để làm việc, bạn có thể sử dụng này:

while read -r line 
do 
    printf "%s\n" "$line" 
done < file.txt 
[[ -n $line ]] && printf '%s' "$line" 

Điều này sẽ làm việc vì thực sự read sẽ đặt dòng cuối cùng vào biến, nhưng nó cũng sẽ trở lại false, do đó phá vỡ vòng lặp while.

Các vấn đề liên quan