回答:
でsed
:
$ echo "123456789" | sed 's/\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)/\1,\2,\3/g'
123,456,789
(これは正確に9桁でのみ機能することに注意してください!)
またはこれでsed
:
$ echo "123456789" | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
123,456,789
でprintf
:
$ LC_NUMERIC=en_US printf "%'.f\n" 123456789
123,456,789
echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g"){sub(",$",""); print}'
sed
機能するのは、数字が正確に9桁の場合のみです。のprintf
はzshでは機能しません。したがって、2番目sed
答えがおそらく最良です。
echo 123456789 | awk '{printf ("%'\''d\n", $0)}'
(明らかにLinuxで常に動作するとは限らない!?が、AIXとSolarisでは正常に動作する)
bash
printf
サポートあなたが行うことができますほとんどすべてprintf
のC関数を
type printf # => printf is a shell builtin
printf "%'d" 123456 # => 123,456
printf
coreutilsからも同じことが行われます
/usr/bin/printf "%'d" 1234567 # => 1,234,567
vsnprintf
です。GNU / Linuxシステムでは、glibcが、少なくとも1995年以来、それを支えてきたように見える
locale -a
。私は使用しなければなりen_US.utf8
numfmtを使用できます。
$ numfmt --grouping 123456789
123,456,789
または:
$ numfmt --g 123456789
123,456,789
numfmtはPOSIXユーティリティではなく、GNU coreutilsの一部であることに注意してください。
-d, --grouping
、二重ハイフネーションには長いオプションが必要なため、次のように記述しますか?
--g
代わりに、私のために罰金を働き--grouping
、すなわちnumfmt --g 1234567890
とnumfmt --grouping 1234567890
同じことを行います。その非常に便利な小さなユーティリティ。
cat <<'EOF' |
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
EOF
perl -wpe '1 while s/(\d+)(\d\d\d)/$1,$2/;'
生成するもの:
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
これは、数字の文字列を2つのグループに分割することで達成されます。右側のグループは3桁、左側のグループは残りのものがありますが、少なくとも1桁です。次に、すべてがコンマで区切られた2つのグループに置き換えられます。これは、置換が失敗するまで続きます。オプション「wpe」はエラーのリスト用で、ステートメントを自動印刷でループ内に囲み、次の引数をperl「プログラム」として取ります(詳細については、perldoc perlrunコマンドを参照してください)。
最高の願い...乾杯、DRL
BASH
/ AWK
代替を要求しましたPERL
。いずれにせよ、コマンドが何をするのかを説明するのが最善です-特にワンライナーの場合。
私の一般的な使用例は、コマンドパイプラインの出力を変更して、10進数が千の区切り文字で印刷されるようにすることです。むしろ機能やスクリプトを書くよりも、私は私がその場でカスタマイズできるという技術を使用することを好む任意の Unixのパイプラインからの出力を。
私はprintf
、これを達成するための最も柔軟で記憶に残る方法である(Awk提供)ことを発見しました。アポストロフィ/シングルクォート文字は、10進数をフォーマットするための修飾子としてPOSIXによって指定され、カンマ文字の使用に制限されないため、ロケールを認識するという利点があります。
UnixシェルからAwkコマンドを実行する場合、単一引用符で区切られた文字列内に単一引用符を入力するのが難しい場合があります(たとえば、位置変数のシェル拡張を避けるため$1
)。この場合、シングルクォート文字を入力する最も読みやすく信頼性の高い方法は、8進エスケープシーケンスとして入力することです(先頭は\0
)。
例:
printf "first 1000\nsecond 10000000\n" |
awk '{printf "%9s: %11\047d\n", $1, $2}'
first: 1,000
second: 10,000,000
どのディレクトリが最もディスク容量を使用しているかを示すパイプラインのシミュレーション出力:
printf "7654321 /home/export\n110384 /home/incoming\n" |
awk '{printf "%22s: %9\047d\n", $2, $1}'
/home/export: 7,654,321
/home/incoming: 110,384
他のソリューションは、awk内の単一引用符をエスケープする方法にリストされています。
注:「一重引用符の印刷」で警告されているように、16進のエスケープシーケンスは異なるシステム間で確実に機能しないため、使用を避けることをお勧めします。
\047
。
awk
そしてbash
良いが内蔵されているソリューションに基づいてprintf
、他の回答で説明したように。しかし、最初にsed
。
のためにsed
、「手動で」それを行う必要があります。一般的な規則は、4桁の連続した数字の後に非数字(または行末)が続く場合、最初の数字と2番目の数字の間にコンマを挿入することです。
例えば、
echo 12345678 | sed -re 's/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/'
印刷します
12345,678
十分なコンマを追加し続けるために、明らかにプロセスを繰り返し続ける必要があります。
sed -re ' :restart ; s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/ ; t restart '
に sed
、コマンドはt
、最後のs///
コマンドが成功した場合にジャンプするラベルを指定します。したがって、:restart
ジャンプして戻るために、でラベルを定義します。
任意の桁数で機能するbashデモ(ideone)を次に示します。
function thousands {
sed -re ' :restart ; s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/ ; t restart '
}
echo 12 | thousands
echo 1234 | thousands
echo 123456 | thousands
echo 1234567 | thousands
echo 123456789 | thousands
echo 1234567890 | thousands
大きな数字を見ていると、上記のソリューションを機能させることができませんでした。たとえば、非常に大きな数を取得できます。
$ echo 2^512 |bc -l|tr -d -c [0-9]
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
注:tr
bcからバックスラッシュ改行出力を削除する必要があります。この数はawkで浮動小数点数または固定ビット数として扱うには大きすぎるため、sedのすべての桁を考慮に入れるのに十分な大きさの正規表現を作成したくはありません。むしろ、私はそれを逆にして、3桁のグループの間にコンマを入れてから、逆にすることができます:
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
awk: run time error: improper conversion(number 1) in printf("%'d
。
a="13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096"
echo "$a" | rev | sed "s#[[:digit:]]\{3\}#&,#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
sed 's/^,//g'
ます。
また、小数点区切り文字の後の部分を正しく分離/スペースしたかったので、いくつかのシェル変数を使用して地域や個人の好みに合わせて調整するこのsedスクリプトを書きました。また、一緒にグループ化される桁数のさまざまな規則も考慮します。
#DECIMALSEP='.' # usa
DECIMALSEP=',' # europe
#THOUSSEP=',' # usa
#THOUSSEP='.' # europe
#THOUSSEP='_' # underscore
#THOUSSEP=' ' # space
THOUSSEP=' ' # thinspace
# group before decimal separator
#GROUPBEFDS=4 # china
GROUPBEFDS=3 # europe and usa
# group after decimal separator
#GROUPAFTDS=5 # used by many publications
GROUPAFTDS=3
function digitgrouping {
sed -e '
s%\([0-9'"$DECIMALSEP"']\+\)'"$THOUSSEP"'%\1__HIDETHOUSSEP__%g
:restartA ; s%\([0-9]\)\([0-9]\{'"$GROUPBEFDS"'\}\)\(['"$DECIMALSEP$THOUSSEP"']\)%\1'"$THOUSSEP"'\2\3% ; t restartA
:restartB ; s%\('"$DECIMALSEP"'\([0-9]\{'"$GROUPAFTDS"'\}\'"$THOUSSEP"'\)*\)\([0-9]\{'"$GROUPAFTDS"'\}\)\([0-9]\)%\1\3'"$THOUSSEP"'\4% ; t restartB
:restartC ; s%\([^'"$DECIMALSEP"'][0-9]\+\)\([0-9]\{'"$GROUPBEFDS"'\}\)\($\|[^0-9]\)%\1'"$THOUSSEP"'\2\3% ; t restartC
s%__HIDETHOUSSEP__%\'"$THOUSSEP"'%g'
}
A bash
/ awk
番号および使用の長さに関係なく動作する(要求されたように)溶液,
ロケールのに関係なくthousands_sep
設定、数字を入力しているとどこで後千枚のセパレータを追加することを回避します1.12345
。
echo not number 123456789012345678901234567890 1234.56789 |
awk '{while (match($0, /(^|[^.0123456789])[0123456789]{4,}/))
$0 = substr($0, 1, RSTART+RLENGTH-4) "," substr($0, RSTART+RLENGTH-3)
print}'
与える:
not number 123,456,789,012,345,678,901,234,567,890 1,234.56789
そのawk
ような実装でmawk
は区間正規表現演算子をサポートしていないため、正規表現を/(^|[^.0123456789])[0123456789][0123456789][0123456789][0123456789]+/
echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g")'