Câu trả lời:
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 echo
lệ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 bash
chia 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 echo
tài liệu ( bash
lệ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ộ x
biế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, count
hàm chỉ đơn giản là in ra số đối số đã cho. Các 1 2 3
và a b c d
cá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 x
biến. Người mà không có dấu ngoặc kép cho thấy có bốn chữ, "test"
, "1"
, "test"
và "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"
.
Đ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
echo "$(IFS=''; cat text.txt)"
Bash -ge 4 có nội trang tệp bản đồ để đọc các dòng từ đầu vào chuẩn vào một 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
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
Các envdir
tiện ích cung cấp một cách dễ dàng để làm điều này. envdir
sử 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.