2010-05-07 26 views
72

Tôi có một test.txt tập tin văn bản với các nội dung sau đây:nội dung tệp vào unix biến với dòng mới

text1 
text2 

Và tôi muốn gán nội dung của các tập tin vào một biến UNIX, nhưng khi tôi làm điều này :

testvar=$(cat test.txt) 
echo $testvar 

kết quả là:

text1 text2 

thay vì

text1 
text2 

Ai đó có thể đề xuất cho tôi giải pháp cho việc này không?

+0

UNIX là một hệ điều hành, không phải là một ngôn ngữ lập trình. Bạn đang nói về ngôn ngữ nào? Shell scripting? – LukeN

+0

@Sad Hình như cú pháp bash. –

+0

vâng, đây có phải là bash – Hugo

Trả lời

112

Việc chuyển nhượng không không xóa các ký tự dòng mới, nó thực sự là echo làm điều này. Bạn chỉ cần đặt dấu ngoặc kép quanh chuỗi để duy trì các dòng mới:

echo "$testvar" 

Đây là kết quả bạn muốn. Xem bảng điểm sau đây cho một bản demo:

pax> cat num1.txt ; x=$(cat num1.txt) 
line 1 
line 2 

pax> echo $x ; echo '===' ; echo "$x" 
line 1 line 2 
=== 
line 1 
line 2 

Các lý do tại sao dòng mới được thay thế bằng không gian không phải là hoàn toàn để làm với lệnh echo, chứ không phải đó là một sự kết hợp của sự vật.

Khi cho một dòng lệnh, bash chia tách nó thành các từ theo các tài liệu cho IFS biến:

IFS: Field Separator nội được sử dụng để tách từ sau khi mở rộng ... các giá trị mặc định là <space><tab><newline>.

Điều đó chỉ định rằng, theo mặc định, bất kỳ ký tự nào trong ba ký tự đó đều có thể được sử dụng để chia lệnh của bạn thành từng từ riêng lẻ. Sau đó, các dấu phân cách từ đã biến mất, tất cả những gì bạn còn lại là một danh sách các từ.

Kết hợp với các tài liệu echo (một lệnh nội bash), và bạn sẽ thấy lý do tại sao không gian là đầu ra:

vang [-neE] [arg ...]: Output args, cách nhau bởi dấu cách, theo sau là một dòng mới.

Khi bạn sử dụng echo "$x", nó buộc toàn bộ biến x là một đơn từ theo bash, do đó nó không được chia. Bạn có thể thấy điều đó với:

pax> function count { 
...> echo $# 
...> } 
pax> count 1 2 3 
3 
pax> count a b c d 
4 
pax> count $x 
4 
pax> count "$x" 
1 

Ở đây, hàm count chỉ in ra số lượng đối số đã cho. Các biến thể 1 2 3a b c d cho biết nó hoạt động.

Sau đó, chúng tôi thử với hai biến thể trên biến số x. Số không có dấu ngoặc đơn cho biết có bốn từ, "test", "1", "test""2". Thêm dấu ngoặc kép làm cho nó một từ đơn "test 1\ntest 2".

+0

tại sao echo làm theo cách này? – Rocky

+0

@Rocky, tôi đã thêm chi tiết hơn một chút vào câu trả lời giải thích lý do. Hy vọng nó giúp. – paxdiablo

+0

Cảm ơn @paxdiablo, điều đó có ý nghĩa. :) – Rocky

8

Điều này là do IFS (Internal Field Separator) biến có chứa dòng mới.

$ cat xx1 
1 
2 

$ A=`cat xx1` 
$ echo $A 
1 2 

$ echo "|$IFS|" 
|  
| 

Một cách giải quyết là để thiết lập lại IFS không chứa newline, tạm:

$ IFSBAK=$IFS 
$ IFS=" " 
$ A=`cat xx1` # Can use $() as well 
$ echo $A 
1 
2 
$ IFS=$IFSBAK 

để trở lại sự thay đổi khủng khiếp này cho IFS:

IFS=$IFSBAK 
+0

cách đặt lại tính năng này không? – Pooja25

+0

Tôi đã thực hiện thay đổi này nhưng bây giờ những thứ khác của tôi không hoạt động, hãy cho tôi biết để đặt lại? – Pooja25

8

Bash -ge 4 có bản dựng sẵn bản đồ để đọc các dòng từ đầu vào chuẩn thành biến mảng.

help mapfile 

mapfile < file.txt lines 
printf "%s" "${lines[@]}" 

mapfile -t < file.txt lines # strip trailing newlines 
printf "%s\n" "${lines[@]}" 

Xem thêm:

http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile

1

Chỉ cần nếu ai đó quan tâm đến việc lựa chọn khác:

content=($(cat test.txt)) 

a=0 
while [ $a -le ${#content[@]} ] 
do 
     echo ${content[$a]} 
     a=$[a+1] 
done 
0

Tiện ích envdir cung cấp một cách dễ dàng để làm điều này. envdir sử dụng các tệp để biểu diễn các biến môi trường, với ánh xạ tên tệp thành tên env var và ánh xạ nội dung tệp thành giá trị env var. Nếu nội dung tập tin có chứa dòng mới, do đó, các env var.

Xem https://pypi.python.org/pypi/envdir

2

biến của bạn được thiết lập một cách chính xác bởi testvar=$(cat test.txt). Để hiển thị biến này bao gồm các ký tự dòng mới, chỉ cần thêm dấu ngoặc kép, ví dụ:

echo "$testvar" 

Dưới đây là toàn bộ ví dụ:

$ printf "test1\ntest2" > test.txt 
$ testvar=$(<test.txt) 
$ grep testvar <(set) 
testvar=$'test1\ntest2' 
$ echo "$testvar" 
text1 
text2 
$ printf "%b" "$testvar" 
text1 
text2 
Các vấn đề liên quan