sed ล้มเหลวในการลบอักขระบรรทัดใหม่


12

ฉันเคยใช้sedมาระยะหนึ่งแล้ว แต่นี่เป็นเรื่องแปลกที่ฉันมาด้วยซึ่งฉันไม่สามารถแก้ไขได้

ให้ฉันอธิบายปัญหาของฉันกับกรณีจริง


ฉาก # 1

printf "ls" | xclip -selection clipboard
echo "ls" | xclip -selection clipboard

ในคำสั่งแรกฉันไปป์printfเอาท์พุทxclipเพื่อที่จะได้รับการคัดลอกไปยังคลิปบอร์ด ตอนนี้สิ่งที่printfแตกต่างechoไม่ได้แทรกบรรทัดใหม่ในตอนท้ายโดยค่าเริ่มต้น ดังนั้นหากฉันวางเนื้อหานี้ลงในเทอร์มินัลlsคำสั่งที่คัดลอกจะไม่ทำงานโดยอัตโนมัติ

ในวินาทีมีบรรทัดใหม่ในตอนท้ายดังนั้นการวางเนื้อหาของคลิปบอร์ดยังส่งผลให้การรันคำสั่งในคลิปบอร์ด

นี่เป็นสิ่งที่ไม่พึงปรารถนาสำหรับฉัน ดังนั้นฉันต้องการลบการขึ้นบรรทัดใหม่โดยใช้sedแต่มันล้มเหลวดังอธิบายในฉากด้านล่าง

ฉาก # 2

echo "ls" | sed -r 's/\n//g' | xclip -selection clipboard

เนื้อหาในคลิปบอร์ดยังมีบรรทัดใหม่ เมื่อฉันวางลงในเทอร์มินัลคำสั่งจะทำงานโดยอัตโนมัติ

\rฉันยังพยายามเอาตัวละครที่กลับรถ แต่นาดา ดูเหมือนว่าฉันขาดสิ่งที่สำคัญมาก / พื้นฐานไปที่นี่

คำตอบ:


16

seddelimits บน\newlines - พวกมันจะถูกลบในอินพุตและแทรกเข้าไปใหม่ในเอาต์พุต นอกจากนี้ไม่เคย\nตัวอักษร ewline ในsedพื้นที่รูปแบบที่ไม่ได้เกิดขึ้นเป็นผลมาจากการแก้ไขที่คุณได้ทำ หมายเหตุ: มีข้อยกเว้นของ GNU sed's -zโหมด ...

เพียงใช้tr:

echo ls | tr -d \\n | xclip -selection clipboard

หรือดีกว่าลืมsedไปเลย:

printf ls | xclip -selection clipboard

สิ่งนี้จะลบบรรทัดใหม่ทั้งหมดซึ่งมักไม่เป็นที่ต้องการในgenerate-text | xclipกรณีนี้ คำตอบนี้จะลบ newline สุดท้ายเท่านั้น
Tom Hale

7

เครื่องมือประมวลผลข้อความจำนวนมากรวมถึง sed ทำงานกับเนื้อหาของบรรทัดยกเว้นอักขระขึ้นบรรทัดใหม่ สิ่งแรกที่ทำเมื่อประมวลผลบรรทัดคือตัดบรรทัดขึ้นบรรทัดใหม่ในตอนท้ายจากนั้นจะดำเนินการคำสั่งในสคริปต์และเพิ่มบรรทัดใหม่สุดท้ายเมื่อพิมพ์ออกมา ดังนั้นคุณจะไม่สามารถลบบรรทัดใหม่ด้วย sed

หากต้องการลบบรรทัดใหม่ทั้งหมดคุณสามารถใช้trแทน:

echo "ls" | tr -d '\n' | xclip


4

คุณสามารถแทนที่บรรทัดใหม่ใน sed โดยส่งผ่านตัวเลือก-z

sed -z 's/\n/ /g'

หน้าคนเกลี้ยกล่อม:

-z, - ไม่มีข้อมูลแยกบรรทัดด้วยอักขระ NUL


การทำเช่นนี้จะลบบรรทัดใหม่ทั้งหมดซึ่งโดยทั่วไปจะไม่ต้องการใน| xclipกรณีนี้
Tom Hale

2

หากคุณเพียงแค่ใส่คำสั่งในคลิปบอร์ด

echo -n "ls " | xclip -selection clipboard

หากคุณต้องการเปลี่ยนแปลงที่ซับซ้อนยิ่งขึ้น

echo "ls  " | perl -pe 's/\n//' | xclip -selection clipboard

อืมมม ทางออกที่ราบรื่น ฉันเดาว่าอาจถึงเวลาแล้วที่จะไปยัง perl หรือ python สำหรับ regex
shivams

3
@shivams - perlและpythonทั้งคู่ช้ากว่ามากsedเมื่อใช้อย่างถูกต้อง แม้ว่าการเรียนรู้ที่จะใช้อย่างถูกต้องเป็นกุญแจสำคัญ
mikeserv

@mikeserv - ฉันเห็นด้วย; พิเศษสำหรับ oneliner sed เป็นสิ่งที่ยอดเยี่ยม หากการเปลี่ยนแปลงกำลังจะซับซ้อนมากขึ้นฉันก็ชอบ perl / python / gawk
JJoao

1
@JJoa: การตั้งค่าของคุณเป็นของคุณเอง แต่sedสามารถทำได้มากกว่าจัดการเพียงหนึ่ง liners ของคุณและมันสามารถทำได้เร็วกว่าเครื่องมืออื่น ๆ ที่คุณพูดถึง
mikeserv

1
@mikeserv - อีกครั้งฉันเห็นด้วยกับคุณ เมื่อหลายปีก่อนฉันมีระบบแปลภาษา EN-PT เขียนใน sed (20,000 s /.../.../) สร้างโดย sed! และมันก็ใช้งานได้! ต่อมามันกลายเป็น Perl เพื่อให้มีอาร์เรย์แฮชฟังก์ชันแพคเกจและ CPAN
JJoao

1

หากต้องการลบเฉพาะบรรทัดใหม่ล่าสุดให้ไพพ์ผ่าน:

sed -z '$ s/\n$//'

sedจะไม่เพิ่ม a \0ถึงจุดสิ้นสุดของสตรีมหากตัวคั่นถูกตั้งค่าเป็นNULผ่าน-zในขณะที่สร้างไฟล์ข้อความ POSIX (กำหนดเป็นสิ้นสุดใน a \n) มันจะส่งออกสุดท้าย\nโดยไม่ต้องใช้-zเสมอ

เช่น:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

และเพื่อพิสูจน์ว่าไม่มีการNULเพิ่ม:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

หากต้องการลบบรรทัดใหม่ที่ต่อท้ายหลายรายการให้ไพพ์ผ่าน:

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