Cách thêm dòng mới khi sử dụng echo


42

Tại sao lệnh sau không chèn các dòng mới vào tệp được tạo và giải pháp là gì?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2

6
echobắt buộc không? bạn có thể sử dụng printf.
Archemar

Tôi không biết về printf, với printf nó hoạt động: P ... vậy thì nó làm gì để không hoạt động với echo?
Saeid Yazdani

Được \rbao gồm trong đầu ra hoặc nó là một phần của CRLFdòng mới?
cuonglm

9
Có nhiều cách thực hiện echolệnh khác nhau không tương thích với nhau. Vì vậy, nên sử dụng công cụ tiêu chuẩn hơn như printf. Xem unix.stackexchange.com/questions/65804/ Khăn để biết tổng quan mở rộng về vấn đề.
jimmij

Trong Stack Overflow, Echo newline in Bash in chữ \ nEcho dòng mới trong Bash in chữ \ n có một số câu trả lời hữu ích.
Graham Perrin

Câu trả lời:


38

echo


Việc echotriển khai tuân thủ nghiêm ngặt Thông số kỹ thuật Unix đơn sẽ thêm dòng mới nếu bạn thực hiện:

echo 'line1\nline2'

Nhưng đó không phải là một hành vi đáng tin cậy. Trên thực tế, thực sự không có bất kỳ hành vi tiêu chuẩn nào mà bạn có thể mong đợi echo.

TOÁN HẠNG

string

Một chuỗi được ghi vào đầu ra tiêu chuẩn. Nếu toán hạng đầu tiên là -nhoặc nếu bất kỳ toán hạng nào chứa ký tự < \backslash> , kết quả được xác định theo thực hiện .

Trên các hệ thống tuân thủ XSI , nếu toán hạng đầu tiên là -n, nó sẽ được coi là một chuỗi, không phải là một tùy chọn . Các chuỗi ký tự sau phải được nhận dạng trên các hệ thống tuân thủ XSI trong bất kỳ đối số nào:

\a- Viết một <cảnh báo> .

\b- Viết một <backspace> .

\c- Loại bỏ <newline> nếu không tuân theo đối số cuối cùng trong đầu ra. Tất cả các ký tự theo sau \ctrong các đối số sẽ được bỏ qua.

\f- Viết một <form-feed> .

\n- Viết một <dòng mới> .

\r- Viết một <xe ngựa trở về> .

\t- Viết một <tab> .

\v- Viết <tab dọc> .

\\- Viết ký tự <backslash> .

\0num- Viết giá trị 8 bit là số bát phân 0, một, hai hoặc ba chữ số num.

Và do đó, thực sự không có bất kỳ cách chung nào để biết cách viết một dòng mới echo, ngoại trừ việc bạn thường có thể dựa vào việc làm echođể làm như vậy.

Một bashshell thường không phù hợp với đặc điểm kỹ thuật, và xử lý -ncác tùy chọn và các tùy chọn khác, nhưng ngay cả điều đó là không chắc chắn. Bạn có thể làm:

shopt -s xpg_echo
echo hey\\nthere

hey
there

thậm chí không cần thiết nếu bashđã được xây dựng với tùy chọn thời gian xây dựng ...

--enable-xpg-echo-default

Làm cho các ký tự echodựng sẵn mở rộng dấu gạch chéo ngược theo mặc định, mà không yêu cầu -etùy chọn. Điều này đặt giá trị mặc định của xpg_echotùy chọn shell thành on, làm cho Bash echohoạt động giống với phiên bản được chỉ định trong Đặc tả Unix đơn, phiên bản 3. Xem Bash Buildins , để biết mô tả về các chuỗi thoát echonhận ra.


printf


Mặt khác, printfhành vi của nó khá thuần phục so với.

CƠ SỞ LÝ LUẬN

Các printftiện ích đã được bổ sung để cung cấp chức năng mà trong lịch sử được cung cấp bởi echo. Tuy nhiên, do sự khác biệt không thể hòa giải trong các phiên bản khác nhau echo, phiên bản này có một số tính năng đặc biệt, để lại những printftiện ích mới này , dựa trên một trong hệ thống Phiên bản thứ chín.

Phần MÔ TẢ EXTENDED gần như khớp chính xác với printf()chức năng trong tiêu chuẩn ISO C, mặc dù nó được mô tả theo các ký hiệu định dạng tệp trong Ký hiệu định dạng tệp XBD .

Nó xử lý các chuỗi định dạng mô tả các đối số của nó - có thể là bất kỳ số lượng nào, nhưng đối với các chuỗi có khá nhiều %bchuỗi %syte hoặc các chuỗi theo nghĩa đen . Khác với các %formats trong đối số đầu tiên, nó hoạt động giống như một %bđối số chuỗi yte, ngoại trừ việc nó không xử lý \cthoát.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Xem tại sao printftốt hơn echo? để biết thêm


echo() printf


Bạn có thể viết tiêu chuẩn của riêng bạn phù hợp echonhư ...

echo(){
    printf '%b ' "$@\n\c"
}

... Điều mà khá nhiều luôn luôn làm điều đúng tự động.

Trên thực tế, không ... Điều đó in một chữ theo \nđuôi của các đối số nếu đối số cuối cùng kết thúc bằng một số lẻ <dấu gạch chéo ngược> .

Nhưng điều này không:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac

+1 cho shopt -s xpg_echotùy chọn echosử dụng -etheo mặc định.
Vignesh Raja

Giải pháp này không hoạt động mà không có -e. Tôi ngạc nhiên khi không ai nhận thấy điều đó ngoại trừ có lẽ @HaydeSchiff
ha9u63ar

@ ha9u63ar - uhh ... bạn đã đọc cái này chưa?
mikeerv

27

Vượt qua cờ -e để lặp lại để làm cho nó phân tích các ký tự thoát, chẳng hạn như "\ r \ n", như vậy:

echo -e "Line 1\r\nLine2" >> readme.txt

Một tùy chọn "-e" đơn giản để làm cho các chuỗi thoát hoạt động - nó nói trên một câu trả lời khác echokhông đáng tin cậy và không tuân theo các tiêu chuẩn không giống như printf.
Edward

1
Đảm bảo tập lệnh của bạn không chứa bất kỳ chữ \ r \ n nào, chẳng hạn như trong một tr -d "\n"lệnh.
Noumenon

8

Trong tất cả các phiên bản bash tôi đã sử dụng, bạn có thể chỉ cần chèn một dòng mới bằng chữ vào một chuỗi tương tác hoặc trong một tập lệnh, với điều kiện là chuỗi đó được trích dẫn đầy đủ.

Tương tác:

$ echo "Line one
> Line two"
Line one
Line two
$

Trong một kịch bản:

echo "Line one
Line two"

4
echo -e "Line 1\r\nLine2" >> readme.txt

khả năng sử dụng hơn nữa:

man echo

2

Mọi người đã trả lời thỏa đáng, nhưng tôi từ chối chấp nhận một thế giới nơi tiếng vang chấp nhận bất kỳ lựa chọn nào khác ngoài -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3

1

Nếu bạn có một nhân vật không phải là một phần của tin nhắn, bạn có thể chuyển qua sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
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.