2012-06-11 22 views
17

Trong Java, nếu bạn biết chắc chắn một tệp rất nhỏ, bạn có thể sử dụng phương thức readBytes() để đọc nội dung trong một lần thay vì đọc từng dòng hoặc sử dụng bộ đệm.Cách đọc nội dung tệp thành một biến trong một lần?

Chỉ cần tự hỏi trong shell script, tôi biết chúng tôi có thể làm điều gì đó như:

while read line 
    do 
     echo $line 
     LINE = $line 
    done < "test.file" 
    echo $LINE 

Nếu test.file của tôi là như sau:

testline1 
testline2 
testline3 

này chỉ mang lại cho tôi những dòng cuối cùng để $LINE. $LINE chứa "testline3".

Câu hỏi của tôi là: Làm cách nào để đọc toàn bộ tệp với nhiều dòng vào một biến duy nhất, vì vậy tôi có thể nhận được $LINE="testline1\ntestline2\ntestline3"?

+1

'data = $ (cat file)', Nhưng vì sao bạn lại muốn có nó? Chỉ cần đọc tệp bất cứ khi nào bạn cần nội dung! –

+1

Hai điều không liên quan trực tiếp đến câu hỏi của bạn: đầu tiên, 'LINE = $ line' không thực sự hoạt động; khoảng trống xung quanh dấu bằng biểu hiện nó không hợp lệ. Thứ hai, nếu bạn đang thao tác văn bản mà bạn muốn giữ nguyên theo nghĩa đen, bạn nên đặt 'IFS' thành null cho các cuộc gọi đã đọc của bạn (nếu không thì khoảng trống trên mỗi dòng sẽ bị nuked) và chuyển tùy chọn' -r' thành 'read' và tùy chọn '-E' thành' echo' (nếu không, mọi dấu gạch chéo ngược trong tệp của bạn sẽ làm mọi thứ lộn xộn). Xem câu trả lời của tôi dưới đây chẳng hạn. –

+0

@MarkReed: Tôi chưa bao giờ hiểu mục đích của '-E' vì đó là hành vi mặc định của Bash cho' echo'. –

Trả lời

56

Xử lý các đường bên trong vòng lặp thay vì sau vòng lặp. Nếu bạn thực sự cần tệp trong một biến:

var=$(<file) 
+0

Bạn cũng có thể giải thích những gì đang xảy ra ở đây? – sbhatla

+2

@sbhatla: Biến được đặt thành giá trị của lệnh thay thế có chứa chuyển hướng đọc nội dung của tệp. Nó tương tự như 'var = $ (cat file)' nhưng nó không yêu cầu sinh ra một file thực thi bên ngoài). –

8

Tùy chọn khác, bạn có thể tạo một dãy các dòng. Nếu bạn đang chạy bash 4+, bạn có thể sử dụng được xây dựng trong mapfile:

mapfile -t lines <test.file 

Nếu bạn muốn các dòng để có sản lượng cũng như lưu trữ, bạn có thể làm một cái gì đó như thế này:

mapfile -t lines < <(tee /dev/tty <test.file) 

Sau đó, "${lines[0]}" sẽ là dòng đầu tiên của tệp, "${lines[1]}" thứ hai, v.v. ${#lines[@]} sẽ là số dòng; "${lines[@]}" sẽ là toàn bộ mảng, trong khi "${lines[*]}" sẽ là các đường nối với nhau bằng dấu cách thành một chuỗi lớn.

Đối với phiên bản cũ của bash, bạn có thể xây dựng mảng một cách thủ công:

lines=() 
while IFS= read -r line 
do 
    printf '%s\n' "$line" 
    lines+=("$line") 
done < test.file 
+1

Điều này sẽ dễ dàng hơn bằng văn bản như 'LINES + = (" $ line ")', phải không? –

+0

Yup. Tôi đã học được một chút trong 4 năm, có vẻ như. Tốt để biết.:) –

+0

Tôi không nghi ngờ nó trong một giây :) –

10

Một lựa chọn khác là sử dụng mapfile BUILTIN đẹp:

mapfile < test.file 
echo "${MAPFILE[@]}" 
+2

Không có trang người đàn ông cho nó, nhưng 'help mapfile' sẽ cung cấp thêm một số thông tin. Tiện ích theo mặc định sẽ đặt dòng đầu tiên vào mục 0, dòng thứ hai vào mục 1, v.v. Bạn cũng có thể muốn sử dụng nó với tùy chọn '-t' (dải mới). – parvus

+1

Lưu ý rằng 'mapfile' đã được giới thiệu trong bash 4, vì vậy không có trong'/bin/bash' trên OS X. Mà có lẽ là pháo đài cuối cùng của bash 3 có khả năng gặp phải trong tự nhiên, nhưng cũng không có khả năng được cập nhật do mối quan tâm cấp phép với Apple và GPL mới. –

+1

Khi Apple cập nhật từ Mac OS lên Macos, bash 4.4 đã được bao gồm. – DopeGhoti

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