Bash: ลากเส้น linebreak ต่อท้ายจากเอาท์พุท


189

เมื่อฉันรันคำสั่งใน Bash (หรือเฉพาะเจาะจงwc -l < log.txt) เอาต์พุตจะมี linebreak หลังจากนั้น ฉันจะกำจัดมันได้อย่างไร

คำตอบ:


251

หากผลลัพธ์ที่คุณคาดหวังเป็นบรรทัดเดียวคุณสามารถลบอักขระบรรทัดใหม่ทั้งหมดออกจากผลลัพธ์ได้ มันจะไม่ผิดปกติไปป์ไปยังยูทิลิตี้ 'tr' หรือ Perl หากต้องการ:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

คุณยังสามารถใช้การทดแทนคำสั่งเพื่อลบบรรทัดขึ้นบรรทัดใหม่:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

โปรดทราบว่าฉันไม่เห็นด้วยกับการตัดสินใจของ OP เพื่อเลือกคำตอบที่ยอมรับได้ ฉันเชื่อว่าควรหลีกเลี่ยงการใช้ 'xargs' หากเป็นไปได้ ใช่มันเป็นของเล่นที่ยอดเยี่ยม ไม่คุณไม่ต้องการที่นี่


หากผลลัพธ์ที่คาดหวังของคุณอาจมีหลายบรรทัดคุณต้องตัดสินใจอีกครั้ง:

หากคุณต้องการลบอักขระบรรทัดใหม่หลายรายการจากท้ายไฟล์ให้ใช้การทดแทน cmd อีกครั้ง:

printf "%s" "$(< log.txt)"

หากคุณต้องการลบอักขระบรรทัดใหม่ล่าสุดออกจากไฟล์ให้ใช้ Perl:

perl -pe 'chomp if eof' log.txt


โปรดทราบว่าถ้าคุณแน่ใจว่าคุณมีอักขระขึ้นบรรทัดใหม่ที่คุณต้องการลบคุณสามารถใช้ 'head' จาก GNU coreutils เพื่อเลือกทุกอย่างยกเว้นไบต์สุดท้าย นี่ควรจะค่อนข้างเร็ว:

head -c -1 log.txt

นอกจากนี้เพื่อความสมบูรณ์คุณสามารถตรวจสอบได้อย่างรวดเร็วว่าอักขระขึ้นบรรทัดใหม่ของคุณ (หรือพิเศษอื่น ๆ ) อยู่ในไฟล์ของคุณโดยใช้ 'cat' และธง 'show-all' อักขระเครื่องหมายดอลลาร์จะระบุจุดสิ้นสุดของแต่ละบรรทัด:

cat -A log.txt

แถบนี้จะขึ้นบรรทัดใหม่ทั้งหมดจากผลลัพธ์ไม่ใช่แค่ขึ้นบรรทัดใหม่ตามที่ชื่อถาม
Cody A. Ray

@ CodyA.Ray: คุณต้องยอมรับว่าคำถามอธิบายคำสั่งเฉพาะที่จะสร้างผลลัพธ์เพียงบรรทัดเดียว อย่างไรก็ตามฉันได้อัปเดตคำตอบเพื่อให้เหมาะกับกรณีทั่วไปมากขึ้น HTH
Steve

3
สิ่งนี้จะดีกว่าถ้าตัวเลือกสั้น ๆ ถูกแทนที่ด้วยตัวเลือกแบบยาว tr --delete '\n'ตัวเลือกการสอนยาวเช่นเดียวกับฟังก์ชั่นเช่น
Elijah Lynn

1
ฉันก็ทำเช่นนั้น| tr -d '\r'
AlikElzin-kilaka

เป็นที่น่าสังเกตว่าโซลูชันการทดแทน cmd อาจนำไปสู่เส้นที่ยาวเกินไปหากไฟล์มีขนาดใหญ่มาก
phk

88

ทางเดียว:

wc -l < log.txt | xargs echo -n

24
ดีกว่า:echo -n `wc -l log.txt`
Satya

9
เหตุใดการประมวลผลคำสั่งใน backticks จึงดีกว่าการใช้ไพพ์
Matthew Schinckel

2
สิ่งเหล่านี้จะไม่เพียงลบ newlines ต่อท้าย แต่ยังบีบ whitespaces ต่อเนื่องใด ๆ (แม่นยำยิ่งขึ้นตามที่กำหนดโดยIFS) ไปยังพื้นที่หนึ่ง ตัวอย่าง: echo "a b" | xargs echo -n; echo -n $(echo "a b"). นี่อาจเป็นปัญหาของกรณีใช้งานหรือไม่ก็ได้
musiphil

14
ที่เลวร้ายยิ่งถ้าการส่งออกเริ่มต้นด้วยก็จะถูกตีความว่าเป็นตัวเลือกที่จะ-e echoมันปลอดภัยกว่าที่จะใช้printf '%s'เสมอ
musiphil

1
xargsช้ามากในระบบของฉัน (และฉันสงสัยว่ามันเป็นระบบอื่น ๆ ด้วย) ดังนั้นprintf '%s' $(wc -l log.txt)อาจเร็วกว่าเนื่องจากprintfปกติแล้วจะเป็นแบบบิลท์อิน (เช่นกันเนื่องจากไม่มีการเปลี่ยนเส้นทางข้อมูล) ไม่เคยใช้ backticks พวกเขาเลิกใช้แล้วในเวอร์ชัน POSIX ที่ใหม่กว่าและมีข้อเสียมากมาย
yyny

14

นอกจากนี้ยังมีการสนับสนุนโดยตรงสำหรับการลบช่องว่างในการแทนที่ตัวแปร Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}

1
คุณสามารถใช้trailing_linebreak_removed=${testvar%?}
PairedPrototype

โปรดทราบว่าหากคุณใช้การทดแทนคำสั่งคุณไม่จำเป็นต้องทำอะไรเพื่อลบบรรทัดใหม่ต่อท้าย Bash ทำเช่นนั้นในฐานะเป็นส่วนหนึ่งของการทดแทนคำสั่ง: gnu.org/software/bash/manual/html_node/…
Michael Burr

10

หากคุณกำหนดเอาต์พุตของมันให้กับตัวแปรให้ตัดbashช่องว่างออกโดยอัตโนมัติ:

linecount=`wc -l < log.txt`

10
การขึ้นบรรทัดใหม่จะถูกปล้น มันคือการทดแทนคำสั่งที่ลบออกไม่ใช่การกำหนดตัวแปร
chepner

2
ฉันเคยเห็นใน Cygwin ทุบช่องว่างท้ายที่ไม่ได้ลบออกเมื่อใช้ $ (cmd / c echo% VAR%) ในกรณีนี้ฉันต้องใช้ $ {var %% [[: space:]]}}
Andrey Taranov

1
หมายเหตุ: ไม่ใช่การกำหนดตัวแปร แต่เป็นการขยายนิพจน์ที่ลบบรรทัดใหม่
Ciro Santilli 郝海东冠状病六四事件法轮功

10

printf ครอบตัดบรรทัดใหม่สำหรับคุณแล้ว:

$ printf '%s' $(wc -l < log.txt)

รายละเอียด:

  • printf จะพิมพ์เนื้อหาของคุณในตำแหน่งของตัว%sยึดตำแหน่งสตริง
  • หากคุณไม่บอกให้พิมพ์บรรทัดใหม่ ( %s\n) จะไม่เกิดขึ้น

7
หากคุณใส่เครื่องหมายคำพูดคู่ล้อมรอบคำสั่งเช่น"$(command)"บรรทัดใหม่ภายในจะถูกเก็บไว้ - และบรรทัดใหม่ที่ต่อท้ายเท่านั้นที่จะถูกลบออก เปลือกทำทุกงานที่นี่ - เป็นเพียงวิธีการเพื่อนำผลลัพธ์ของคำสั่งเปลี่ยนตัวกลับไปยังprintf stdout
Brent Bradburn

2
มันไม่ใช่ printf ที่ลอกบรรทัดใหม่ที่นี่มันคือเชลล์ที่ทำกับ$( )โครงสร้าง นี่คือข้อพิสูจน์:printf "%s" "$(perl -e 'print "\n"')"
Flimm

อีกครั้งเป็นที่น่าสังเกตว่าบรรทัดคำสั่งผลลัพธ์อาจยาวเกินไป
phk

นี่เป็นวิธีที่สะดวกด้วยคำแนะนำของ @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim

10

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

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+$//'

ฉันคิดว่านี้เป็นส่วนขยายของ GNU, Mac ไม่ได้ให้sed -z
Spidey

7

หากคุณต้องการพิมพ์เอาต์พุตของสิ่งใด ๆ ใน Bash โดยไม่ต้องวางสายคุณจะต้องแสดงด้วย-nสวิตช์

หากคุณมีมันอยู่ในตัวแปรแล้วสะท้อนให้เห็นด้วยการขึ้นบรรทัดใหม่ตัดต่อท้าย :

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar

หรือคุณสามารถทำได้ในหนึ่งบรรทัดแทน:

    $ echo -n $(wc -l < log.txt)

2
ตัวแปรไม่จำเป็นทางเทคนิค echo -n $(wc -l < log.txt)มีผลเหมือนกัน
chepner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.