Dengan python
re.sub(r"(?<=.)(?=(?:...)+$)", ",", stroke )
Untuk membagi angka dengan kembar tiga, misalnya:
echo 123456789 | python -c 'import sys;import re; print re.sub(r"(?<=.)(?=(?:...)+$)", ",", sys.stdin.read());'
123,456,789
Bagaimana melakukan hal yang sama dengan bash / awk?
bash
shell-script
awk
string
pengguna2496
sumber
sumber
echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g")'
echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g"){sub(",$",""); print}'
sed
hanya berfungsi jika jumlahnya tepat 9 digit. Tidakprintf
berfungsi pada zsh. Jadised
jawaban kedua mungkin yang terbaik.echo 123456789 | awk '{printf ("%'\''d\n", $0)}'
(yang ternyata tidak selalu berhasil di Linux!?, Tetapi berfungsi dengan baik di AIX dan Solaris)bash
'sprintf
dukungan cukup banyak segala sesuatu yang dapat Anda lakukan diprintf
fungsi Cprintf
dari coreutils akan melakukan hal yang samasumber
zsh
juga, pos yang diperbarui di sini .vsnprintf
. Pada sistem GNU / Linux, glibc tampaknya telah mendukungnya setidaknya sejak 1995.export LC_NUMERIC="en_US"
jika Anda ingin memaksa koma.locale -a
. Saya harus menggunakanen_US.utf8
Anda dapat menggunakan numfmt:
Atau:
Perhatikan bahwa numfmt bukan utilitas POSIX, itu adalah bagian dari GNU coreutils.
sumber
-d, --grouping
karena tanda hubung ganda membutuhkan opsi yang panjang?--g
berfungsi dengan baik untuk saya daripada--grouping
, yaitunumfmt --g 1234567890
dannumfmt --grouping 1234567890
melakukan hal yang sama. Utilitas kecil yang sangat berguna.menghasilkan:
Ini dilakukan dengan memisahkan string angka menjadi 2 kelompok, kelompok kanan dengan 3 digit, kelompok kiri dengan apa pun yang tersisa, tetapi setidaknya satu digit. Kemudian semuanya digantikan oleh 2 grup, dipisahkan oleh koma. Ini berlanjut sampai substitusi gagal. Pilihan "wpe" adalah untuk daftar kesalahan, lampirkan pernyataan di dalam loop dengan cetak otomatis, dan ambil argumen berikutnya sebagai "program" perl (lihat perintah perldoc perlrun untuk detailnya).
Salam hangat, tepuk tangan, drl
sumber
BASH
/AWK
alternatif sehingga ia mungkin tidak pernah menggunakanPERL
sebelumnya. Dalam hal apa pun, yang terbaik untuk menjelaskan apa yang dilakukan perintah - terutama untuk satu baris.Dengan beberapa
awk
implementasi:"%'"'"'d\n"
adalah:"%
(kutipan tunggal) (penawaran ganda) (penawaran tunggal) (penawaran ganda) (penawaran tunggal) d \ n"
Itu akan menggunakan pemisah ribuan yang dikonfigurasi untuk lokal Anda (biasanya
,
dalam bahasa Inggris lokal, spasi dalam bahasa Prancis,.
dalam bahasa Spanyol / Jerman ...). Sama seperti yang dikembalikan olehlocale thousands_sep
sumber
Kasus penggunaan umum bagi saya adalah untuk memodifikasi output dari pipa perintah sehingga angka desimal dicetak dengan ribuan pemisah. Daripada menulis fungsi atau skrip, saya lebih suka menggunakan teknik yang bisa saya sesuaikan dengan cepat setiap output dari pipa Unix.
Saya telah menemukan
printf
(disediakan oleh Awk) sebagai cara yang paling fleksibel dan mudah diingat untuk mencapai ini. Karakter tanda kutip / kutipan tunggal ditentukan oleh POSIX sebagai a pengubah untuk memformat angka desimal dan memiliki keunggulan yang disadari oleh lokal sehingga tidak dibatasi untuk menggunakan karakter koma.Saat menjalankan perintah Awk dari shell Unix, mungkin ada kesulitan memasukkan karakter tanda kutip di dalam string yang dibatasi oleh tanda kutip tunggal (untuk menghindari shell ekspansi variabel posisi, misalnya,
$1
). Dalam hal ini, saya menemukan cara yang paling mudah dibaca dan dapat diandalkan untuk memasukkan karakter tanda kutip tunggal adalah dengan memasukkannya sebagai urutan pelepasan oktal (dimulai dengan\0
).Contoh:
Output simulasi pipa yang menunjukkan direktori mana yang menggunakan ruang disk paling banyak:
Solusi lain tercantum di Cara keluar dari kutipan tunggal di dalam awk .
Catatan: seperti diperingatkan dalam Cetak Kutipan Tunggal , disarankan untuk menghindari penggunaan urutan pelepasan heksadesimal karena mereka tidak bekerja dengan andal di berbagai sistem.
sumber
\047
.awk
danbash
memiliki solusi bawaan yang baik, berdasarkanprintf
, seperti yang dijelaskan dalam jawaban lain. Tapi pertama-tama,sed
,.Untuk
sed
, kita perlu melakukannya "secara manual". Aturan umum adalah bahwa jika Anda memiliki empat digit berturut-turut, diikuti oleh non-digit (atau end-of-line) maka koma harus dimasukkan antara digit pertama dan kedua.Sebagai contoh,
akan dicetak
Kita jelas perlu untuk kemudian terus mengulangi prosesnya, untuk terus menambahkan cukup koma.
Di
sed
,t
perintah menentukan label yang akan dilompati jikas///
perintah terakhir berhasil. Karena itu saya mendefinisikan label dengan:restart
, agar melompat kembali.Berikut ini adalah demo bash (pada ideone ) yang bekerja dengan sejumlah digit:
sumber
sumber
Jika Anda melihat nomor BESAR saya tidak dapat membuat solusi di atas berfungsi. Misalnya, mari kita dapatkan angka yang sangat besar:
$ echo 2^512 |bc -l|tr -d -c [0-9] 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
Catatan Saya perlu
tr
untuk menghapus output baris baru backslash dari bc. Angka ini terlalu besar untuk diperlakukan sebagai angka bit mengambang atau tetap dalam awk, dan saya bahkan tidak ingin membangun regexp yang cukup besar untuk memperhitungkan semua angka dalam sed. Sebaliknya, saya dapat membalikkannya dan menempatkan koma di antara kelompok tiga digit, lalu membatalkannya:echo 2^512 |bc -l|tr -d -c [0-9] |rev |sed -e 's/\([0-9][0-9][0-9]\)/\1,/g' |rev 13,407,807,929,942,597,099,574,024,998,205,846,127,479,365,820,592,393,377,723,561,443,721,764,030,073,546,976,801,874,298,166,903,427,690,031,858,186,486,050,853,753,882,811,946,569,946,433,649,006,084,096
sumber
awk: run time error: improper conversion(number 1) in printf("%'d
.sumber
sed 's/^,//g'
.Saya juga ingin memiliki bagian setelah para pemisah desimal benar dipisahkan / spasi, karena itu saya menulis ini sed-naskah yang menggunakan beberapa variabel shell untuk menyesuaikan dengan preferensi regional dan pribadi. Ini juga memperhitungkan konvensi yang berbeda untuk jumlah digit yang dikelompokkan bersama :
sumber
Solusi A
bash
/awk
(seperti yang diminta) yang berfungsi terlepas dari panjang angka dan penggunaannya,
terlepas dari pengaturan lokalthousands_sep
, dan di mana pun angka-angka itu di input dan menghindari menambahkan ribuan pemisah setelah di1.12345
:Memberi:
Dengan
awk
implementasi sepertimawk
itu yang tidak mendukung operator regex interval, ubah regexp menjadi/(^|[^.0123456789])[0123456789][0123456789][0123456789][0123456789]+/
sumber