Bash: Strip trailing linebreak dari output

189

Ketika saya menjalankan perintah di Bash (atau lebih spesifik, wc -l < log.txt), output berisi linebreak setelahnya. Bagaimana saya menyingkirkannya?

hexacyanide
sumber

Jawaban:

251

Jika output yang diharapkan adalah satu baris , Anda dapat menghapus semua karakter baris baru dari output. Tidak jarang pipa ke utilitas 'tr', atau Perl jika lebih disukai:

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

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

Anda juga dapat menggunakan substitusi perintah untuk menghapus baris tambahan:

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

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

Harap dicatat bahwa saya tidak setuju dengan keputusan OP untuk memilih jawaban yang diterima. Saya percaya orang harus menghindari menggunakan 'xargs' jika memungkinkan. Ya, itu mainan yang keren. Tidak, Anda tidak membutuhkannya di sini.


Jika output yang diharapkan dapat berisi banyak baris , Anda harus membuat keputusan lain:

Jika Anda ingin menghapus beberapa karakter baris baru dari akhir file, gunakan kembali substitusi cmd:

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

Jika Anda ingin benar-benar menghapus karakter baris baru THE LAST dari file, gunakan Perl:

perl -pe 'chomp if eof' log.txt


Perhatikan bahwa jika Anda yakin memiliki karakter baris baru yang ingin Anda hapus, Anda dapat menggunakan 'head' dari GNU coreutils untuk memilih semuanya kecuali byte terakhir. Ini harus cukup cepat:

head -c -1 log.txt

Selain itu, untuk kelengkapan, Anda dapat dengan cepat memeriksa di mana karakter baris baru Anda (atau karakter khusus lainnya) ada di file Anda menggunakan 'cat' dan flag 'show-all'. Karakter tanda dolar akan menunjukkan akhir dari setiap baris:

cat -A log.txt
Steve
sumber
Ini menghapus SEMUA baris baru dari output, bukan hanya baris tambahan saat judulnya bertanya.
Cody A. Ray
@ CodyA.Ray: Anda harus setuju, bahwa pertanyaan tersebut menggambarkan perintah khusus yang hanya akan menghasilkan satu baris output. Namun, saya telah memperbarui jawaban saya agar sesuai dengan kasus yang lebih umum. HTH.
Steve
3
Ini akan lebih baik jika opsi pendek diganti dengan opsi panjang. Opsi panjang mengajar serta berfungsi misalnya tr --delete '\n'.
Elijah Lynn
1
Saya juga melakukannya| tr -d '\r'
AlikElzin-kilaka
Perlu dicatat bahwa solusi substitusi cmd mungkin mengarah ke garis yang terlalu panjang jika file tersebut sangat besar.
phk
88

Satu arah:

wc -l < log.txt | xargs echo -n
Satya
sumber
24
Lebih baik:echo -n `wc -l log.txt`
Satya
9
Mengapa melakukan eksekusi perintah di backticks lebih baik daripada menggunakan pipa?
Matthew Schinckel
2
Ini tidak hanya akan menghapus baris baru, tetapi juga menekan spasi putih berurutan (lebih tepatnya, sebagaimana didefinisikan oleh IFS) ke satu spasi. Contoh: echo "a b" | xargs echo -n; echo -n $(echo "a b"). Ini mungkin atau mungkin tidak menjadi masalah untuk kasus penggunaan.
musiphil
14
Lebih buruk lagi, jika output dimulai dengan -e, itu akan ditafsirkan sebagai opsi untuk echo. Itu selalu lebih aman untuk digunakan printf '%s'.
musiphil
1
xargssangat lambat pada sistem saya (dan saya menduga itu pada sistem lain juga), jadi printf '%s' $(wc -l log.txt)mungkin lebih cepat, karena printfbiasanya builtin (Juga karena tidak ada pengalihan informasi). Jangan pernah menggunakan backticks, mereka telah usang dalam versi POSIX yang lebih baru dan memiliki banyak kelemahan.
yyny
14

Ada juga dukungan langsung untuk menghilangkan white space di substitusi variabel Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Andrey Taranov
sumber
1
Anda juga dapat menggunakantrailing_linebreak_removed=${testvar%?}
PairedPrototype
Perhatikan bahwa jika Anda menggunakan substitusi perintah maka Anda tidak perlu melakukan apa pun untuk menghapus trailing newlines. Bash sudah melakukan itu sebagai bagian dari penggantian perintah: gnu.org/software/bash/manual/html_node/…
Michael Burr
10

Jika Anda menetapkan outputnya ke variabel, bashsecara otomatis menghapus spasi:

linecount=`wc -l < log.txt`
nneonneo
sumber
10
Trailing newlines dilucuti, tepatnya. Substitusi perintah yang menghapusnya, bukan penugasan variabel.
chepner
2
Saya telah melihat di Cygwin bash spasi spasi tidak dihapus saat menggunakan $ (cmd / c echo% VAR%). Dalam hal ini saya harus menggunakan $ {var %% [[: space:]]}.
Andrey Taranov
1
Catatan: ini bukan tugas variabel, tetapi ekspansi ekspresi yang menghapus baris baru.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
10

printf sudah memotong baris tambahan untuk Anda:

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

Detail:

  • printf akan mencetak konten Anda di %stempat dudukan string.
  • Jika Anda tidak mengatakannya untuk mencetak baris baru ( %s\n), itu tidak akan.
nol2cx
sumber
7
Jika Anda menempatkan tanda kutip ganda sekitar perintah seperti "$(command)", baris baru internal yang akan dipertahankan - dan hanya mengikuti baris akan dihapus. Shell sedang melakukan semua pekerjaan di sini - printfhanyalah cara untuk mengarahkan kembali hasil substitusi perintah stdout.
Brent Bradburn
2
Bukan printf yang membuka baris baru di sini, tetapi shell yang melakukannya dengan $( )konstruk. Ini buktinya:printf "%s" "$(perl -e 'print "\n"')"
Flimm
Sekali lagi, perlu dicatat bahwa baris perintah yang dihasilkan mungkin menjadi terlalu panjang.
phk
Ini adalah solusi yang mudah dengan saran @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim
10

Jika Anda ingin menghapus hanya baris baru terakhir , pipa melalui:

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

sedtidak akan menambahkan \0ke akhir aliran jika pembatas diatur ke NULvia -z, sedangkan untuk membuat file teks POSIX (didefinisikan berakhir di a \n), selalu akan menghasilkan akhir \ntanpa -z.

Misalnya:

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

Dan untuk membuktikan tidak ada yang NULditambahkan:

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

Untuk menghapus beberapa baris baru , ikuti :

sed -Ez '$ s/\n+$//'
Tom Hale
sumber
Saya kira ini adalah ekstensi GNU, Mac sedtidak menyediakan -z.
Spidey
7

Jika Anda ingin mencetak output apa pun di Bash tanpa akhir baris, Anda menggema dengan -nsaklar.

Jika Anda sudah memilikinya di variabel, gema dengan baris baru yang dipotong:

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

Atau Anda dapat melakukannya dalam satu baris, sebagai gantinya:

    $ echo -n $(wc -l < log.txt)
Rastislav Hasicek
sumber
2
Variabel secara teknis tidak perlu. echo -n $(wc -l < log.txt)memiliki efek yang sama.
chepner