บรรทัดใหม่ใน sed บน Mac OS X


44

ฉันพบว่า\nใช้งานไม่ได้ในระบบปฏิบัติการภายใต้ Mac OS X โดยเฉพาะฉันต้องการแบ่งคำออกเป็นหลายช่อง:

# input
foo bar

ฉันใช้,

echo "foo bar" | sed 's/ /\n/'

แต่ผลที่ได้คือโง่\nไม่หนี!

foonbar

หลังจากที่ฉันปรึกษากับ google ฉันพบวิธีแก้ปัญหา :

echo 'foo bar' | sed -e 's/ /\'$'\n/g'

หลังจากอ่านบทความฉันยังไม่เข้าใจความ\'$'\n/g'หมาย บางคนสามารถอธิบายให้ฉันหรือถ้ามีวิธีอื่นที่จะทำ? ขอบคุณ!


นี้อาจจะทำงานมากเกินไป:echo "foo bar" | tr ' ' '\n'
เกล็น Jackman

3
ขอบคุณสำหรับคำแนะนำ. \nแต่ขณะนี้ผมเพียงแค่ใช้กรณีข้างต้นเป็นตัวอย่างที่ผมไม่จำเป็นต้องรู้วิธีที่จะหลบหนี
Ivan ZG เสี่ยว

สำเนาซ้ำที่เป็นไปได้: stackoverflow.com/questions/21621722/…
hyiltiz

คำตอบ:


27

คุณสามารถbrew install gnu-sedเปลี่ยนการโทรไปด้วยsedgsed

หากคุณไม่ต้องการที่จะย่อหน้า "G" เพื่อsedคุณสามารถและเพียงแค่โทรbrew install gnu-sed --with-default-namessed

(แก้ไข: อัปเดตสถานะการชง, คำแนะนำหมวกเป็นClément)


การใช้ซอฟต์แวร์เดียวกันบนทุกแพลตฟอร์มนั้นเป็นวิธีที่ง่ายกว่า (สำหรับฉัน) และเป็นวิธีที่ง่ายกว่าการจัดการกับทุกรุ่นของ Mac ระวังตัวเลือกอยู่ในขณะนี้--with-default-namesและไม่ได้ --default-namesอย่างไรก็ตามตัวเลือกนี้ใช้ไม่ได้กับการติดตั้งของฉันดังนั้นฉันต้องใส่ตัวalias gsed=sedเอง~/.profileเพื่อให้มันใช้งานได้
Clément

4
นี่เป็นวิธีแก้ปัญหาที่น่าเกลียด ไม่ได้อธิบายว่าทำไมsedใน OS X จึงทำงานเหมือนที่เคยทำและทำให้สมมติฐานที่gnu-sedไม่ถูกต้องนั้นถูกต้องมากขึ้น อย่าเป็นคนติด GNU และยึดติดกับมาตรฐาน POSIX เพื่อหลีกเลี่ยงปัญหาในระยะยาว
octosquidopus

เป็นวิธีที่ Apple ควรทำให้ระบบปฏิบัติการทำงานเป็นค่าเริ่มต้น เหตุใดจึงใช้ชื่อของโปรแกรมแล้วทำให้มันทำงานแตกต่างกัน? ฉันเสียเวลาหนึ่งชั่วโมงเพราะเหตุนี้ ...
rascio

@rascio - เนื่องจาก OS X เป็นแบบ BSD และ Linux เป็นแบบ Linux
iAdjunct

@rascio ฉันคิดว่าคุณจะพบว่า GNU sed เป็นผู้ใช้ใหม่ BSD วันที่กลับไปปี 1979 (ดูen.wikipedia.org/wiki/Version_7_Unix )
Duncan Bayne

24

สิ่งเหล่านี้จะทำงาน:

echo 'foo bar' | sed 's/ /\
/g'

echo 'foo bar' | sed $'s/ /\\\n/g'

lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"

sed ของ OS X ไม่ได้ตีความ\nในรูปแบบการแทนที่ แต่คุณสามารถใช้การป้อนบรรทัดตามตัวอักษรที่นำหน้าด้วยอักขระการต่อบรรทัด เชลล์แทนที่$'\n'ด้วยตัวป้อนบรรทัดตามตัวอักษรก่อนที่คำสั่ง sed จะรัน


4
ทำไมไม่sed $'s/ /\\\n/g'ทำงาน แต่ไม่ได้sed $'s/\\\n/ /g'?
Alec Jacobson

1
@alec คุณไม่สามารถใช้งานsedได้แม้ใน linux / unix เพื่อลบบรรทัดใหม่เนื่องจากแยกวิเคราะห์ / แยกที่บรรทัดใหม่แต่ละบรรทัด หากคุณทำงานนี้ใน Linux / UNIX ก็จะไม่ทำอะไรอย่างใดอย่างหนึ่งecho -e 'foo\nbar' | sed 's/\n//'
wisbucky

10

sed -eวิธีแก้ปัญหาที่คุณพบผ่านสตริงอาร์กิวเมนต์เดียวเพื่อ

อาร์กิวเมนต์นั้นจบลงด้วยการเป็นสตริงในs/ / /gรูปแบบsed ที่คุ้นเคย

สายนั้นถูกสร้างขึ้นในสองส่วนหนึ่งหลังจากที่อื่น

ส่วนแรกจะถูกยกมาใน'...'รูปแบบ

ส่วนที่สองถูกยกมาใน$'...'รูปแบบ

's/ /\'ส่วนหนึ่งได้รับ-ราคาเดียวถอด แต่อย่างอื่นผ่านไป sed เช่นเดียวกับลักษณะที่ปรากฏบนบรรทัดคำสั่ง นั่นคือแบ็กสแลชไม่ได้ถูกทุบด้วยการทุบตี

$'\n/g'ส่วนหนึ่งได้รับเครื่องหมายดอลลาร์เดี่ยวและคำพูดถอดและ\nได้รับการแปลงเป็นตัวอักษรขึ้นบรรทัดใหม่

ทั้งหมดเข้าด้วยกันการโต้เถียงกลายเป็น

s / / \ newline/ g

[นั้นน่าสนุก. ใช้เวลาสักครู่เพื่อแกะที่ +1 สำหรับคำถามที่น่าสนใจ]


7

การแสดงออก$'...'เป็นbash-ism ซึ่งสร้างขึ้น...ด้วยลำดับหนีมาตรฐานขยาย Th ก่อนมันก็หมายความทับขวาตามด้วยส่วนท้ายของยกที่สตริงที่เกิดคือ\' s/ /\(ใช่คุณสามารถสลับข้อความในช่วงกลางของสตริงมันไม่ได้จบสตริง)

มาตรฐาน POSIX sedยอมรับเฉพาะ\nเป็นส่วนหนึ่งของรูปแบบการค้นหา OS X ใช้ FreeBSD sedซึ่งเป็นไปตาม POSIX อย่างเคร่งครัด ตามปกติแล้ว GNU จะเพิ่มสิ่งเพิ่มเติมจากนั้นผู้ใช้ Linux ทุกคนก็คิดว่าเป็น "มาตรฐาน" (บางทีฉันอาจจะประทับใจมากกว่านี้หากพวกเขามีกระบวนการมาตรฐาน)


ตอนนี้ฉันเข้าใจ$'...'ส่วนนั้นแล้ว แต่ ... อะไรนะs/ /\ ? คุณหมายถึงswitch quotingอะไร
Ivan ZG เสี่ยว

2
'...'เป็นหนึ่งในประเภทของการอ้างเปลือก; $'...'เป็นอีก นอกจากนี้ยังมี"..."และ\xเพื่ออ้างถึงตัวละครตัวเดียว คุณสามารถรวมผู้ที่อยู่ในคำเดียวซึ่งเป็นสิ่งที่กำลังทำมีการเปลี่ยนจากปกติ''สตริงกับสตริงการแปล$'' \nสำหรับส่วนที่เหลือมันสร้างsedคำสั่ง ( s/text/replacement/flags) ในกรณีนี้คำสั่งจะเริ่มต้นรวมถึงแบ็กสแลชที่ส่วนท้ายเพื่อป้องกันการขึ้นบรรทัดใหม่ตามตัวอักษรที่$'\n/g'ผนวก ผลลัพธ์คือการแทนที่/gช่องว่าง( แฟล็ก) ทั้งหมดด้วยบรรทัดใหม่
geekosaur

1

มีเรื่องง่ายมากที่จะมองเห็นสิ่งที่เกิดขึ้น เพียงแค่สะท้อนสตริง!

echo 's/$/\'$'\n/g'

ผลลัพธ์ใน

s/$/\
/g

ซึ่งเทียบเท่ากับ s/$/\newline/g

หากคุณไม่ได้มีการเสริม\ก่อนหน้าnewlineเปลือกจะตีความnewlineว่าเป็นจุดสิ้นสุดของคำสั่งก่อนเวลาอันควร

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