Khi tôi làm
str="Hello World\n===========\n"
Tôi nhận được \n
in ra quá. Làm thế nào tôi có thể có dòng mới sau đó?
Khi tôi làm
str="Hello World\n===========\n"
Tôi nhận được \n
in ra quá. Làm thế nào tôi có thể có dòng mới sau đó?
Câu trả lời:
Trong bash
bạn có thể sử dụng cú pháp
str=$'Hello World\n===========\n'
Các dấu ngoặc đơn đứng trước a $
là một cú pháp mới cho phép chèn các chuỗi thoát trong chuỗi.
Ngoài ra printf
nội dung cho phép lưu kết quả đầu ra vào một biến
printf -v str 'Hello World\n===========\n'
Cả hai giải pháp không yêu cầu một subshell.
Nếu trong phần sau bạn cần in chuỗi, bạn nên sử dụng dấu ngoặc kép, như trong ví dụ sau:
echo "$str"
bởi vì khi bạn in chuỗi không có dấu ngoặc kép, dòng mới được chuyển thành khoảng trắng.
str=$'Hello World\n===========\n'
được gọi là gì? thay thế?
zsh
và ksh
; tuy nhiên, nó không tuân thủ POSIX.
str=$"My $PET eats:\n$PET food"
? Cách tiếp cận này hoạt động cho dấu ngoặc kép
Bạn có thể đặt các dòng mới theo nghĩa đen trong các dấu ngoặc đơn (trong bất kỳ vỏ kiểu Bourne / POSIX nào).
str='Hello World
===========
'
Đối với một chuỗi nhiều dòng, ở đây các tài liệu thường thuận tiện. Chuỗi được cung cấp như là đầu vào cho một lệnh.
mycommand <<'EOF'
Hello World
===========
EOF
Nếu bạn muốn lưu trữ chuỗi trong một biến, hãy sử dụng cat
lệnh thay thế lệnh. (Các) ký tự dòng mới ở cuối chuỗi sẽ bị tước bằng cách thay thế lệnh. Nếu bạn muốn giữ lại các dòng mới cuối cùng, hãy đặt một nút chặn ở cuối và loại bỏ nó sau đó. Trong các shell tương thích POSIX, bạn có thể viết str=$(cat <<'EOF'); str=${str%a}
theo sau bởi heredoc thích hợp, nhưng bash yêu cầu heredoc xuất hiện trước dấu ngoặc đơn đóng.
str=$(cat <<'EOF'
Hello World
===========
a
EOF
); str=${str%a}
Trong ksh, bash và zsh, bạn có thể sử dụng $'…'
biểu mẫu được trích dẫn để mở rộng dấu gạch chéo ngược bên trong dấu ngoặc kép.
str=$'Hello World\n===========\n'
str=$(cat <<'EOF')
không hoạt động như hiện tại .. Các )
nhu cầu phải được đặt ở dòng tiếp theo sau khi kết thúc tài liệu EOF
.. nhưng ngay cả như vậy, nó bị mất dòng mới do Lệnh Thay thế.
\n
trong bash
khi chụp tài liệu ở đây trong một biến, hãy xem xét IFS= read -r -d '' str <<'EOF'...
như một cách thay thế cho phương pháp chặn (xem câu trả lời của tôi).
Bạn đang sử dụng "tiếng vang"? Hãy thử "echo -e".
echo -e "Hello World\n===========\n"
echo
sẽ tự động thêm một cái, trừ khi bạn chỉ định -n. (Tuy nhiên, vấn đề chính của câu hỏi là làm thế nào để đưa các dòng mới này vào một biến).
bash
, echo -e
không hoạt động trên OS X - đó là vì echo
một bash dựng sẵn (chứ không phải là một thực thi bên ngoài) và nội dung đó hỗ trợ -e
. (Như một dựng sẵn, nó sẽ hoạt động trên tất cả các nền tảng mà bash chạy trên; tình cờ, echo -e
làm việc trong ksh
và zsh
quá). Tuy nhiên, ngược lại, tiện ích bên ngoàiecho
trên OS X - /bin/echo
- thực sự không hỗ trợ -e
.
Nếu bạn cần dòng mới trong tập lệnh của mình nhiều lần, bạn có thể khai báo một biến toàn cục đang giữ một dòng mới. Bằng cách đó, bạn có thể sử dụng nó trong chuỗi trích dẫn kép (mở rộng biến).
NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"
$''
cần một subshell?
"My dog eats:${NL}dog food"
Để bổ sung cho các câu trả lời tuyệt vời hiện có:
Nếu bạn đang sử dụng bash
và bạn thích sử dụng các dòng mới thực sự để dễ đọc , read
là một tùy chọn khác để ghi lại một tài liệu ở đây trong một biến , mà (giống như các giải pháp khác ở đây) không yêu cầu sử dụng một mạng con.
# Reads a here-doc, trimming leading and trailing whitespace.
# Use `IFS= read ...` to preserve it (the trailing \n, here).
read -r -d '' str <<'EOF' # Use `IFS= read ...` to preserve the trailing \n
Hello World
===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"
[Hello World
===========]
-r
đảm bảo rằng read
không diễn giải đầu vào (theo mặc định, nó sẽ xử lý dấu gạch chéo ngược đặc biệt, nhưng điều đó hiếm khi cần thiết).
-d ''
đặt dấu phân cách "bản ghi" thành một chuỗi trống, khiến read
cho việc đọc toàn bộ đầu vào cùng một lúc (thay vì chỉ một dòng).
Lưu ý rằng bằng cách để $IFS
mặc định $' \t\n'
( dấu phân cách trường bên trong) ở mặc định, ( khoảng trắng , tab, dòng mới), mọi khoảng trắng ở đầu và cuối được cắt bớt từ giá trị được gán $str
, bao gồm dòng mới ở đây.
(Lưu ý rằng ngay cả khi phần thân của tài liệu ở đây bắt đầu trên dòng sau dấu phân cách bắt đầu ( 'EOF'
ở đây), nó không chứa dòng mới hàng đầu ).
Thông thường, đây là hành vi mong muốn, nhưng nếu bạn muốn dòng mới đó, hãy sử dụng IFS= read -r -d ''
thay vì chỉ read -r -d ''
, nhưng lưu ý rằng bất kỳ khoảng trắng hàng đầu và dấu nào đều được giữ nguyên.
(Lưu ý rằng việc trả trước IFS=
trực tiếp cho read
lệnh có nghĩa là việc gán chỉ có hiệu lực trong suốt lệnh đó, do đó không cần khôi phục giá trị trước đó.)
Sử dụng tài liệu ở đây cũng cho phép bạn tùy ý sử dụng thụt lề để đặt chuỗi đa dòng cho dễ đọc:
# Caveat: indentation must be actual *tab* characters - spaces won't work.
read -r -d '' str <<-'EOF' # NOTE: Only works if the indentation uses actual tab (\t) chars.
Hello World
===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.
# Note how the leading tabs were stripped.
$ echo "$str"
[Hello World
===========]
Đặt -
giữa <<
và dấu phân cách mở ở đây-doc ( 'EOF'
, ở đây) làm cho các ký tự tab hàng đầu bị xóa khỏi thân tài liệu ở đây và thậm chí là dấu phân cách đóng, nhưng lưu ý rằng điều này chỉ hoạt động với các ký tự tab thực tế , không phải dấu cách, vì vậy nếu biên tập viên dịch phím nhấn vào không gian, cần thêm công việc.
bạn cần làm theo cách này:
STR=$(echo -ne "Hello World\n===========\n")
Cập nhật:
Như Fred đã chỉ ra, theo cách này, bạn sẽ mất dấu "\ n". Để gán biến với các chuỗi d���u gạch chéo ngược được mở rộng, hãy làm:
STR=$'Hello World\n===========\n\n'
Hãy kiểm tra nó:
echo "[[$STR]]"
cho chúng tôi ngay bây giờ:
[[Hello World
===========
]]
Lưu ý rằng $ '' khác với $ "". Thứ hai không dịch theo ngôn ngữ hiện tại. Đối với deital xem phần QUOTING trong man bash
.
#!/bin/bash
result=""
foo="FOO"
bar="BAR"
result+=$(printf '%s' "$foo")$'\n'
result+=$(printf '%s' "$bar")$'\n'
echo "$result"
printf '%s' "$result"
đầu ra:
FOO
BAR
FOO
BAR
result+=$foo$'\n'
? $(printf %s "$foo")
sẽ cắt các ký tự dòng mới trong $foo
nếu có.