วิธีเพิ่มบรรทัดใหม่เมื่อใช้ echo


42

เหตุใดคำสั่งต่อไปนี้จึงไม่แทรกบรรทัดใหม่ในไฟล์ที่สร้างขึ้นและคำตอบคืออะไร

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

$ cat readme.txt 
Line 1\r\nLine2

6
เป็นechoข้อบังคับหรือไม่ printfคุณสามารถใช้
Archemar

ฉันไม่รู้เกี่ยวกับ printf กับ printf มันทำงาน: P ... แล้วมันไม่ทำงานกับ echo ทำไม?
Saeid Yazdani

มีที่\rรวมในการส่งออกหรือเป็นส่วนหนึ่งของCRLFการขึ้นบรรทัดใหม่?
cuonglm

9
มีการใช้งานechoคำสั่งต่าง ๆ ที่เข้ากันไม่ได้ printfดังนั้นจึงขอแนะนำให้ใช้เครื่องมือมาตรฐานมากขึ้นเป็น ดูunix.stackexchange.com/questions/65803/…สำหรับภาพรวมเพิ่มเติมของปัญหา
jimmij

คำตอบ:


38

echo


การechoติดตั้งที่สอดคล้องกับข้อกำหนดของ Unix อย่างเคร่งครัดจะเพิ่มบรรทัดใหม่หากคุณ:

echo 'line1\nline2'

แต่นั่นไม่ใช่พฤติกรรมที่เชื่อถือได้ จริงๆแล้วมันไม่มีพฤติกรรมมาตรฐานใด ๆ ที่คุณคาดหวังechoได้

ถูกดำเนินการ

string

สตริงที่จะเขียนไปยังเอาต์พุตมาตรฐาน ถ้าตัวถูกดำเนินการเป็นครั้งแรก-nหรือถ้าใด ๆ ของตัวถูกดำเนินประกอบด้วย< \ทับขวา>ตัวละครที่ผลการดำเนินงานเป็นที่กำหนดไว้

เมื่อวันที่XSI สอดคล้องระบบถ้าตัวถูกดำเนินการแรกคือ-nมันจะได้รับการปฏิบัติเป็นสตริง, ไม่ได้ตัวเลือก ลำดับอักขระต่อไปนี้จะถูกจดจำบนระบบที่สอดคล้องกับ XSI ภายในอาร์กิวเมนต์ใด ๆ :

\a- เขียน<แจ้งเตือน>

\b- เขียน<Backspace>

\c- ระงับ<newline>ที่ตามหลังอาร์กิวเมนต์สุดท้ายในเอาต์พุต อักขระทั้งหมดที่ตามหลัง\cในอาร์กิวเมนต์จะถูกละเว้น

\f- เขียน<form-feed>

\n- เขียน<newline>

\r- เขียน<ผลตอบแทนการขนส่ง>

\t- เขียน<> แท็บ

\v- เขียน<แนวตั้งแท็บ>

\\- เขียนตัวอักษร<backslash>

\0num- เขียนค่า 8 numบิตที่เป็นศูนย์หนึ่งสองหรือสามหลักตัวเลขฐานแปด

ดังนั้นจึงไม่มีวิธีทั่วไปที่จะรู้วิธีเขียนบรรทัดใหม่ด้วยechoยกเว้นว่าคุณสามารถพึ่งพาเพียงแค่ทำechoเช่นนั้น

bashเปลือกมักจะไม่เป็นไปตามข้อกำหนดและจัดการ-nและตัวเลือกอื่น ๆ แต่แม้ที่มีความไม่แน่นอน คุณทำได้:

shopt -s xpg_echo
echo hey\\nthere

hey
there

และไม่ใช่แม้กระทั่งสิ่งที่จำเป็นหากbashถูกสร้างขึ้นด้วยตัวเลือกบิลด์เวลา ...

--enable-xpg-echo-default

ทำให้echoบิวด์อินขยายอักขระที่ไม่ใช้เครื่องหมายแบคสแลชโดยดีฟอลต์โดยไม่ต้องใช้-eอ็อพชัน สิ่งนี้ตั้งค่าเริ่มต้นของxpg_echoตัวเลือกเชลล์เป็นonซึ่งทำให้ Bash echoทำงานเหมือนรุ่นที่ระบุใน Single Unix Specification รุ่น 3 ดูที่Bash Builtinsสำหรับคำอธิบายของ escape sequences ที่echoรู้จัก


printf


ในทางตรงกันข้ามprintfพฤติกรรมของมันค่อนข้างเชื่องเมื่อเปรียบเทียบ

หลักการและเหตุผล

ยูทิลิตี้ถูกเพิ่มเข้ามาเพื่อให้การทำงานที่ได้รับในอดีตให้บริการโดยprintf echoอย่างไรก็ตามเนื่องจากความแตกต่างที่แก้ไขไม่ได้ในรุ่นที่echoมีอยู่ของรุ่นต่าง ๆทำให้รุ่นนี้มีคุณสมบัติพิเศษไม่กี่อย่างจึงเหลือคุณสมบัติเหล่านี้ไว้ในprintfยูทิลิตี้ใหม่นี้ซึ่งมีพื้นฐานอยู่ในระบบรุ่นที่เก้า

ส่วนรายละเอียด EXTENDED เกือบจะตรงกับprintf()ฟังก์ชั่นในมาตรฐาน ISO C ถึงแม้มันจะอธิบายในแง่ของโน้ตรูปแบบไฟล์ในXBD รูปแบบไฟล์โน้ต

มันจัดการสตริงรูปแบบที่อธิบายถึงข้อโต้แย้งของ - ซึ่งสามารถเป็นจำนวนสิ่งใด ๆ แต่สำหรับสตริงที่มีสวยมากทั้ง%bสตริง yte หรือ%strings ตัวอักษร นอกเหนือจาก%formats ในอาร์กิวเมนต์แรกมันจะทำงานเหมือน%bอาร์กิวเมนต์สตริง yte ส่วนใหญ่ยกเว้นว่ามันจะไม่จัดการกับการ\cหลบหนี

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

^
\n$^    \t$

ดูทำไมจึงprintfดีกว่าecho? มากขึ้น


echo() printf


คุณอาจเขียนมาตรฐานของคุณเองechoเช่น ...

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

... ซึ่งน่าจะทำสิ่งที่ถูกต้องโดยอัตโนมัติ

อันที่จริงไม่ ... นั่นพิมพ์ตัวอักษร\nที่หางของการขัดแย้งถ้าอาร์กิวเมนต์สุดท้ายปลายในเลขคี่ของ<เครื่องหมาย>

แต่นี่ไม่ใช่:

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

+1 สำหรับshopt -s xpg_echoตัวเลือกในechoการใช้งาน-eโดยค่าเริ่มต้น
Vignesh Raja

โซลูชันนี้ใช้งานไม่-eได้ ฉันประหลาดใจที่ไม่มีใครสังเกตเห็นว่ายกเว้น @HaydeSchiff
ha9u63ar

@ ha9u63ar - เอ่อ ... เจ้าอ่านนี่แล้วเหรอ?
mikeserv

27

ผ่านแฟล็ก -e เพื่อ echo เพื่อแยกวิเคราะห์อักขระที่หนีเช่น "\ r \ n" เช่น:

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

ดีง่าย "อี" ตัวเลือกที่จะได้รับลำดับหนีทำงาน - ที่กล่าวในคำตอบที่ว่าคนอื่นจะไม่น่าเชื่อถือและไม่เป็นไปตามมาตรฐานที่แตกต่างจากecho printf
Edward

1
ตรวจสอบให้แน่ใจว่าสคริปต์ของคุณไม่มีตัวอักษร \ r \ n ใด ๆ เช่นในtr -d "\n"คำสั่ง
Noumenon

8

ใน bash ทุกเวอร์ชันที่ฉันใช้คุณอาจแทรก newline ตามตัวอักษรลงในสตริงได้ทั้งแบบโต้ตอบหรือในสคริปต์โดยมีเงื่อนไขว่าสตริงนั้นมีการอ้างอิงอย่างเพียงพอ

โต้ตอบ:

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

ในสคริปต์:

echo "Line one
Line two"

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

ความเป็นไปได้ในการใช้งานเพิ่มเติม:

man echo

2

ผู้คนตอบอย่างเพียงพอแล้ว แต่ฉันปฏิเสธที่จะยอมรับโลกที่เสียงสะท้อนยอมรับตัวเลือกอื่นนอกเหนือจาก-nนี้

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

1

หากคุณมีตัวละครที่ไม่ได้เป็นส่วนหนึ่งของข้อความคุณสามารถไปป์ผ่าน 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.