web-dev-qa-db-ja.com

数字に数千の区切りを追加

Pythonで

 re.sub(r"(?<=.)(?=(?:...)+$)", ",", stroke ) 

トリプレットで数値を分割するには、例えば:

 echo 123456789 | python -c 'import sys;import re; print re.sub(r"(?<=.)(?=(?:...)+$)", ",",  sys.stdin.read());'
 123,456,789

Bash/awkで同じことをするには?

42
user2496

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
35
slm

bashprintfは、printf C関数で実行できるほとんどすべての機能をサポートします

type printf           # => printf is a Shell builtin
printf "%'d" 123456   # => 123,456

coreutilsのprintfも同じです

/usr/bin/printf "%'d" 1234567   # => 1,234,567
54
Mikel

Numfmtを使用できます。

$ numfmt --grouping 123456789
123,456,789

または:

$ numfmt --g 123456789
123,456,789

NumfmtはPOSIXユーティリティではなく、GNU coreutilsの一部です。

8
Steven Penny
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

4
drl

いくつかのawk実装:

echo "123456789" | awk '{ printf("%'"'"'d\n",$1); }'  

123,456,789  

"%'"'"'d\n" is:"%(single quote)(double quote)(single quote)(double quote)(single quote)d\n"

これは、ロケールに構成された1000の区切り文字を使用します(通常、英語ロケールでは,、フランス語ではスペース、スペイン語/ドイツ語では.)。 locale thousands_sepから返されるものと同じ

3
Ben

awkbashには、他の回答で説明されているように、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
3
Aaron McDaid

私の一般的な使用例は、コマンドパイプラインの出力を変更して、10進数が1000のセパレータで出力されるようにすることです。関数やスクリプトを作成するのではなく、Unixパイプラインからのany出力をその場でカスタマイズできる手法を使用することを好みます。

私はprintf(Awkが提供)が最も柔軟で、これを実現するための記憶に残る方法であることがわかりました。アポストロフィ/一重引用符文字は、10進数をフォーマットするために [〜#〜] posix [〜#〜] として 修飾子​​ として指定され、ロケールに対応しているという利点がありますしたがって、コンマ文字の使用に限定されません。

UnixシェルからAwkコマンドを実行する場合、単一引用符で区切られた文字列内に一重引用符文字を入力するのは困難な場合があります(位置変数のシェル拡張を回避するために、$1など)。この場合、一重引用符文字を入力する最も読みやすく信頼できる方法は、octalエスケープシーケンス(\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内の単一引用符をエスケープする方法 にリストされています。

注: Print Single Single Quote で警告されているように、16進数のエスケープシーケンスは異なるシステム間で確実に機能しないため、使用を避けることをお勧めします。

2

数値の長さに関係なく機能し、ロケールの_,_設定に関係なく_thousands_sep_を使用するbash/awkソリューション(および要求されたとおり)ソリューション、および数値入力内にあり、_1.12345_の後に1000の区切り文字を追加しないようにします。

_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]+/に変更します

1
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
1
user2796674
$ echo 1232323 | awk '{printf(fmt,$1)}' fmt="%'6.3f\n"
12,32,323.000
1
Akshay Hegde

あなたが大きな数字を見ているならば、私は上記の解決策を機能させることができませんでした。たとえば、本当に大きな数を取得しましょう:

_$ echo 2^512 |bc -l|tr -d -c [0-9] 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096_

Bcからバックスラッシュの改行出力を削除するには、trが必要です。この数値は大きすぎて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

1

また、afterdecimal separator の部分を正しく分離/配置したかったので、このsed-scriptを作成しました。地域や個人の好みに合わせて調整するシェル変数。また、異なる グループ化された桁数の規則 も考慮に入れます。

#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'
}
0
erik