숫자에 천 단위 구분 기호 추가


36

파이썬에서

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

트리플렛으로 숫자를 나누려면 다음과 같이하십시오.

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

bash / awk와 동일한 작업을 수행하는 방법은 무엇입니까?

답변:


29

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

나는 또한 awk와 함께 노력하고 있지만 마지막에 쉼표를 추가합니다echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g")'
Rahul Patil

지금은 얻을 수 있지만 복잡해 보인다echo 123456789 | awk '$0=gensub(/(...)/,"\\1,","g"){sub(",$",""); print}'
Rahul Patil

1
먼저 sed숫자가 정확히 9 자리 인 경우에만 작동합니다. 은 printfzsh을 작동하지 않습니다. 따라서 두 번째 sed대답은 아마 최고입니다.
Patrick

1
@RahulPatil 자릿수가 3의 배수 인 경우에만 제대로 작동합니다. "12345678"로 시도하면 무슨 뜻인지 알 수 있습니다.
패트릭

1
당신은 할 수 있습니다 echo 123456789 | awk '{printf ("%'\''d\n", $0)}'(확실히 Linux에서는 작동하지 않지만! AIX와 Solaris에서는 제대로 작동합니다)
Johan

51

bashprintf지원은 거의 모든 당신은에서 할 수있는 printfC 기능

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

printf coreutils에서 동일한 작업을 수행합니다

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

이것은 현재 zsh업데이트 된 게시물에서도 지원 됩니다 .
don_crissti

1
나는 bash 4.1.2에 있고 그것을 지원하지 않는다 ... :(
msb

@msb 시스템에 의존하는 것 같습니다 vsnprintf. GNU / 리눅스 시스템에서 glibc는 적어도 1995 년 이후로이를 지원 한 것으로 보입니다.
Mikel

2
참고 printf는 현재 로케일에 천 단위 구분 기호를 사용합니다.이 구분 기호 는 쉼표, 점 또는 전혀 사용할 수 없습니다. 당신은 할 수 있습니다 export LC_NUMERIC="en_US"당신은 쉼표를 강제하려는 경우.
medmunds

로 지원되는 로캘 목록을 가져옵니다 locale -a. 나는 사용해야했다en_US.utf8
eludom

7

numfmt를 사용할 수 있습니다 :

$ numfmt --grouping 123456789
123,456,789

또는:

$ numfmt --g 123456789
123,456,789

numfmt는 POSIX 유틸리티가 아니며 GNU coreutils의 일부입니다.


1
"그룹화"팁에 감사드립니다. 두 번째 예 (--g)에서 -d, --grouping이중 하이픈 넣기에는 긴 옵션이 필요하므로 다음과 같은 내용을 작성 했습니까?
호핑 토끼

--g대신 나를 위해 잘 작동 --grouping, 즉 numfmt --g 1234567890numfmt --grouping 1234567890같은 일을한다. 매우 유용한 작은 유틸리티입니다.
가장 큰

4
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 자리, 왼쪽 그룹은 남아있는 것이지만 적어도 하나의 숫자로 나눕니다. 그런 다음 모든 것이 쉼표로 구분 된 두 그룹으로 대체됩니다. 대체가 실패 할 때까지 계속됩니다. "wpe"옵션은 오류 목록을위한 것이며, 자동 인쇄로 루프 안에 명령문을 묶고 perl "프로그램"으로 다음 인수를 사용하십시오 (자세한 내용은 perldoc perlrun 명령 참조).

최고의 소원 ... 건배, drl


의견을 보내 주셔서 감사합니다. downvote조차도 유용 할 수 있지만 설명 된 경우에만 해당됩니다. 잘못된 점에 대해 의견을 말하십시오. 감사합니다 ... 건배
drl

여기서 공감대는 명령이 수행하는 작업을 설명하지 않았기 때문이라고 생각합니다. 영업 이익은 요청 BASH/ AWK그가 사용하지 않았을 수 있도록 대안 PERL전에. 어쨌든, 명령이 무엇을 하는지를 설명하는 것이 가장 좋습니다.
AnthonyK

@AnthonyK-가능한 설명 감사합니다. 작동 방식을 간단히 설명하기 위해 의견을 추가했습니다. 대체 솔루션이 종종 유용하다고 생각하지만 펄을 사용하지 않았을 가능성에 대한 요점은 다음과 같습니다 ... 건배
drl

이 페이지에서 sed 및 python 제안을 시도했습니다. 펄 스크립트는 전체 파일에서 작동하는 유일한 스크립트였습니다. 파일은 텍스트와 숫자로 정리되었습니다.
Mark

3

일부 awk구현 :

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

123,456,789  

"%'"'"'d\n"is : "%(한 따옴표) (더블 따옴표) (한 따옴표) (더블 따옴표) (한 따옴표) d \ n"

로케일에 대해 구성된 천 단위 구분 기호를 사용합니다 (일반적 ,으로 영어 로케일, 프랑스어 공간, .스페인어 / 독일어 ...). 에서 반환 한 것과 동일locale thousands_sep


2

필자의 일반적인 사용 사례는 십진수가 천 단위 구분 기호로 인쇄되도록 명령 파이프 라인의 출력을 수정하는 것입니다. 오히려 함수 나 스크립트를 작성하는 것보다, 나는에 대한 즉시 사용자 정의 할 수있는 기술을 사용하는 것을 선호 어떤 유닉스 파이프 라인의 출력을.

나는 printf(Awk에서 제공)이 이것을 달성하는 가장 유연하고 기억에 남는 방법이라는 것을 알았습니다 . 아포스트로피 / 작은 따옴표 문자는 POSIX에 의해 10 진수를 형식화하기 위한 수정 자로 지정되며 로케일을 인식하므로 쉼표 문자 사용으로 제한되지 않습니다.

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 진수 이스케이프 시퀀스는 다른 시스템에서 안정적으로 작동하지 않으므로 16 진수 이스케이프 시퀀스를 사용하지 않는 것이 좋습니다.


1
여기에 나열된 모든 awk 기반 답변 중에서 가장 확실합니다 (IMHO). 다른 솔루션과 마찬가지로 다른 따옴표로 견적을 해킹 할 필요가 없습니다.
TSJNachos117

Thanks @ TSJNachos117 가장 어려운 부분은 아포스트로피 문자의 8 진 인코딩이 \047입니다.
Anthony G-Monica에 대한 정의

2

awk그리고 bash내장 된 솔루션을 기반으로 좋은이 printf다른 답변에 설명 된대로. 그러나 먼저 sed.

를 위해서는 sed"수동으로"해야합니다. 일반적인 규칙은 4 개의 연속 숫자가 있고 그 뒤에 숫자가 아닌 (또는 줄 끝) 있으면 첫 번째 숫자와 두 번째 숫자 사이에 쉼표를 삽입해야한다는 것입니다.

예를 들어

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 '

에서 sedt명령은 마지막 경우에 뛰어됩니다 레이블 지정 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


1

BIG 번호를보고있는 경우 위의 솔루션을 작동시킬 수 없었습니다. 예를 들어 정말 큰 숫자를 얻습니다.

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

참고 trBC에서 백 슬래시 줄 바꿈 출력을 제거 해야합니다 . 이 숫자는 awk의 부동 소수점 또는 고정 비트 숫자로 취급하기에는 너무 커서 sed의 모든 숫자를 설명하기에 충분한 정규 표현식을 작성하고 싶지 않습니다. 오히려 나는 그것을 뒤집어서 세 자리 그룹 사이에 쉼표를 넣은 다음 반전시킬 수 있습니다.

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


2
좋은 대답입니다. 그러나 Awk와 함께 많은 수를 사용하는 데 문제가 없었습니다. 많은 Red Hat 및 Debian 기반 배포판에서 예제를 시도했지만 모든 경우에 Awk는 큰 숫자에 아무런 문제가 없었습니다. 나는 그것에 대해 좀 더 생각했고 내가 실험 한 모든 시스템이 64 비트 (지원되지 않는 RHEL 5를 실행하는 아주 오래된 VM조차도)였습니다. 32 비트 OS를 실행하는 오래된 랩톱을 테스트하여 문제를 복제 할 수있을 때까지는 없었습니다 awk: run time error: improper conversion(number 1) in printf("%'d.
Anthony G-

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

숫자의 자릿수가 3의 배수이면 가짜 선행 쉼표가 추가됩니다.
Stéphane Chazelas

@ StéphaneChazelas : 마지막 rev 명령의 출력을 가져 와서 파이프에 넣을 수 sed 's/^,//g'있습니다.
TSJNachos117

0

I는 부분하고 싶어 소수 구분 올바르게 / 분리 이격 따라서 I 지역 및 개인 환경에 적응 일부 쉘 변수를 사용하여이 나오지 스크립트를 썼다. 또한 함께 그룹화 된 자릿수에 대한 다른 규칙을 고려 합니다 .

#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

숫자의 길이에 관계없이 작동 하고 로케일의 설정에 관계없이 사용 되는 bash/ awk(요청에 따라) 솔루션 은 숫자가 입력 위치에 있고 다음에 천 단위 구분 기호를 추가하지 않는 :,thousands_sep1.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]+/

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.