Tệp nội dung vào biến unix với dòng mới


117

Tôi có một tệp văn bản test.txt với nội dung sau:

text1
text2 

Và tôi muốn gán nội dung của tệp cho 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ể gợi ý cho tôi một giải pháp cho điều này?

Câu trả lời:


184

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

echo "$testvar"

Điều này sẽ cho kết quả mà bạn muốn. Xem bản ghi sau để biế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 các echolệnh, chứ không phải đó là một sự kết hợp của sự vật.

Khi được cung cấp một dòng lệnh, hãy bashchia nó thành các từ theo tài liệu choIFS biến:

IFS: Dấu phân tách trường nội bộ được sử dụng để tách từ sau khi mở rộng ... 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ự đó có thể được sử dụng để chia lệnh của bạn thành các từ riêng lẻ. Sau đó, các dấu tách từ biến mất, tất cả những gì bạn còn lại là danh sách các từ.

Kết hợp điều đó với echotài liệu ( bashlệnh nội bộ) và bạn sẽ thấy lý do tại sao các khoảng trắng được xuất ra:

echo [-neE] [arg ...]: Xuất các args, được phân tách bằng 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ộ xbiến phải là một từ duy nhất theo bash, do đó nó không bị tách. 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, counthàm chỉ đơn giản là in ra số đối số đã cho. Các 1 2 3a b c dcác biến thể cho thấy nó hoạt động.

Sau đó, chúng tôi thử nó với hai biến thể trên xbiến. Người mà không có dấu ngoặc kép cho thấy có bốn chữ, "test", "1", "test""2". Thêm dấu ngoặc kép làm cho nó trở thành một từ duy nhất "test 1\ntest 2".


Các dấu ngoặc kép ... đó là những gì tôi đã thiếu! Cảm ơn!
nặc danh

Cũng đáng chú ý: Trailing dòng mới sẽ được gỡ bỏ bởi các nhà điều hành thay thế lệnh bản thân: Hãy thử nó trên mạng!
Jonah

11

Điều này là do biến IFS (Internal Field Separator) 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à đặt lại IFS để không chứa dòng mới, tạm thời :

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

Để REVERT thay đổi khủng khiếp này cho IFS:

IFS=$IFSBAK

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 xin vui lòng cho tôi biết để thiết lập lại nó?
Pooja: 25

Nếu bạn không cần nó để đi đến một biến, một lớp lót trực tiếp:echo "$(IFS=''; cat text.txt)"
Curtis Yallop


3

Chỉ cần ai đó quan tâm đến một tùy chọn khác:

content=( $(cat test.txt) )

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

3

Biến của bạn được đặt đúng 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" 

Đây là ví dụ đầy đủ:

$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2

0

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

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.