एक संख्या में हजारों विभाजक जोड़ें


37

अजगर में

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

किसी संख्या को तीन गुणा करने के लिए, उदाहरण के लिए:

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

बैश / जाग के साथ भी ऐसा ही कैसे करें?

जवाबों:


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

मैं भी अजीब के साथ कोशिश कर रहा हूँ, लेकिन यह आखिरी में अल्पविराम जोड़ रहा हैecho 123456789 | awk '$0=gensub(/(...)/,"\\1,","g")'
राहुल पाटिल

अब मुझे मिलता है लेकिन यह जटिल लगता हैecho 123456789 | awk '$0=gensub(/(...)/,"\\1,","g"){sub(",$",""); print}'
राहुल पाटिल

1
sedअगर नंबर 9 अंकों का है तो यह केवल तभी काम करता है। printfZsh पर काम नहीं करता। इस प्रकार दूसरा sedउत्तर शायद सबसे अच्छा है।
पैट्रिक

1
@RahulPatil केवल तभी ठीक से काम करता है जब अंकों की संख्या कई हो। 3. "12345678" के साथ प्रयास करें और आप देखेंगे कि मेरा क्या मतलब है।
पैट्रिक

1
आप कर सकते हैं echo 123456789 | awk '{printf ("%'\''d\n", $0)}'(जो जाहिर तौर पर लिनक्स पर काम नहीं करता है!?, लेकिन AIX और सोलारिस पर ठीक काम करता है)
जोहान

51

bashके printfसमर्थन काफी सब कुछ आप में कर सकते हैं printfसी समारोह

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
मैं ४.१.२ बैश पर हूँ और यह समर्थन नहीं करता है ...:
एमएसबी

@msb यह आपके सिस्टम पर निर्भर करता है vsnprintf। GNU / Linux सिस्टम पर, glibc कम से कम 1995 के बाद से इसका समर्थन करता प्रतीत होता है।
मिकेल

2
नोट प्रिंटफ़ आपके वर्तमान स्थान के लिए हजारों विभाजक का उपयोग करता है , जो अल्पविराम, बिंदु या कुछ भी नहीं हो सकता है। आप चाहें export LC_NUMERIC="en_US"तो अल्पविराम के लिए मजबूर कर सकते हैं।
शाम

समर्थित लोकेल की सूची प्राप्त करें locale -a। मैं का इस्तेमाल किया थाen_US.utf8
eludom

7

आप numfmt का उपयोग कर सकते हैं:

$ numfmt --grouping 123456789
123,456,789

या:

$ numfmt --g 123456789
123,456,789

ध्यान दें कि numfmt एक POSIX उपयोगिता नहीं है, यह GNU कोरुटिल्स का हिस्सा है।


1
"समूहीकरण" टिप के लिए धन्यवाद। दूसरे उदाहरण (- जी) में, क्या आपको कुछ लिखने का मतलब है -d, --groupingक्योंकि डबल हाइफ़नेशन के लिए लंबे विकल्पों की आवश्यकता है?
बनी

--gके बजाय मेरे लिए ठीक काम करता है --grouping, यानी numfmt --g 1234567890और numfmt --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 अंकों के साथ दाहिने हाथ का समूह, जो भी रहता है उसके साथ बाएं हाथ का समूह, लेकिन कम से कम एक अंक। फिर सब कुछ 2 समूहों द्वारा बदल दिया जाता है, एक अल्पविराम द्वारा अलग किया जाता है। यह तब तक जारी रहता है जब तक प्रतिस्थापन विफल हो जाता है। विकल्प "वेप" त्रुटि लिस्टिंग के लिए हैं, एक लूप के अंदर स्टेटमेंट को एक स्वचालित प्रिंट के साथ संलग्न करें, और अगले तर्क को पर्ल "प्रोग्राम" के रूप में लें (विवरण के लिए कमांड perldoc perlrun देखें)।

शुभकामनाएँ ... चीयर्स, डीएल


प्रतिक्रिया के लिए अनाम के लिए धन्यवाद। यहां तक ​​कि एक downvote उपयोगी हो सकता है, लेकिन केवल अगर समझाया जाए - तो कृपया टिप्पणी करें कि आपने जो देखा वह गलत था। धन्यवाद ... चियर्स
डीआरएल

मुझे लगता है कि यहां की गिरावट इसलिए है क्योंकि आपने यह नहीं बताया कि कमांड क्या करती है। ओपी ने एक विकल्प BASH/ AWKविकल्प मांगा ताकि वह PERLपहले उपयोग न कर सके । किसी भी मामले में, यह समझाने के लिए कि कमांड क्या करता है - विशेष रूप से एक-लाइनर्स के लिए।
एंथनीके

@AnthonyK - संभावित स्पष्टीकरण के लिए धन्यवाद। मैंने टिप्पणियों को संक्षेप में बताया कि यह कैसे काम करता है। मुझे लगता है कि वैकल्पिक समाधान अक्सर उपयोगी होते हैं, लेकिन संभवतः पर्ल के उपयोग के बारे में आपकी बात नोट नहीं की जाती है ... चीयर्स
dr

मैंने इस पेज पर sed और अजगर सुझावों की कोशिश की। पर्ल स्क्रिप्ट एकमात्र ऐसी थी जिसने पूरी फाइल के लिए काम किया। फ़ाइल पाठ और संख्याओं के साथ दायर की गई थी।
मार्क

3

कुछ awkकार्यान्वयन के साथ :

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

123,456,789  

"%'"'"'d\n"है: "%(एकल उद्धरण) (डबल उद्धरण) (एकल उद्धरण) (डबल उद्धरण) (एकल उद्धरण) d \ n"

यह आपके लोकेल के लिए कॉन्फ़िगर किए गए हजार विभाजक (आमतौर ,पर अंग्रेजी स्थानों में, फ्रेंच में स्थान, .स्पेनिश / जर्मन में) का उपयोग करेगा। उसी के अनुसार लौटाlocale thousands_sep


2

मेरे लिए एक सामान्य उपयोग का मामला एक कमांड पाइपलाइन के आउटपुट को संशोधित करना है ताकि दशमलव संख्या हजार विभाजक के साथ मुद्रित हो। एक फ़ंक्शन या स्क्रिप्ट लिखने के बजाय, मैं एक ऐसी तकनीक का उपयोग करना पसंद करता हूं जिसे मैं यूनिक्स पाइपलाइन से किसी भी आउटपुट के लिए मक्खी पर अनुकूलित कर सकता हूं ।

मैंने इसे printfपूरा करने के लिए सबसे अधिक लचीला और यादगार तरीका (Awk द्वारा प्रदान) पाया है । Apostrophe / एकल उद्धरण चरित्र POSIX द्वारा दशमलव संख्याओं को प्रारूपित करने के लिए एक संशोधक के रूप में निर्दिष्ट किया गया है और इसका लाभ यह है कि यह स्थानीय-जागरूक है इसलिए यह अल्पविराम वर्णों का उपयोग करने के लिए प्रतिबंधित नहीं है।

जब यूनिक्स शेल से Awk कमांड्स चल रहे हों, तो सिंगल-कोट्स द्वारा सीलिंग किए गए स्ट्रिंग के अंदर एक सिंग-कोट कैरेक्टर में प्रवेश करने में कठिनाइयाँ हो सकती हैं (पोजिशनल वेरिएबल्स के शेल विस्तार से बचने के लिए, जैसे $1)। इस मामले में, मुझे एकल-उद्धरण चरित्र में प्रवेश करने के लिए सबसे पठनीय और विश्वसनीय तरीका मिला है, इसे एक ऑक्टल एस्केप सीक्वेंस (शुरुआत के साथ \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

अन्य समाधानों को सूचीबद्ध किया गया है कि कैसे जाग के अंदर एक उद्धरण से बचने के लिए

नोट: जैसा कि प्रिंट एक एकल उद्धरण में चेतावनी दी गई है , यह हेक्साडेसिमल एस्केप अनुक्रमों के उपयोग से बचने के लिए अनुशंसित है क्योंकि वे विभिन्न प्रणालियों में मज़बूती से काम नहीं करते हैं।


1
यहां सूचीबद्ध सभी अजीब-आधारित उत्तरों में से, यह सबसे निश्चित रूप से सबसे सुंदर (IMHO) है। एक को अन्य समाधानों की तरह एक उद्धरण में हैक करने की आवश्यकता नहीं है।
TSJNachos117

धन्यवाद @ TSJNachos117 सबसे कठिन हिस्सा यह याद कर रहा है कि एपोस्ट्रोफ चरित्र के लिए ऑक्टल एन्कोडिंग है \047
एंथोनी जी -

2

awkऔर bashअच्छे अंतर्निर्मित समाधान हैं, printfजो अन्य उत्तरों में वर्णित के आधार पर हैं । लेकिन पहले, sed

इसके लिए sed, हमें इसे "मैन्युअल रूप से" करने की आवश्यकता है। सामान्य नियम यह है कि यदि आपके पास लगातार चार अंक हैं, उसके बाद एक गैर-अंक (या अंत-पंक्ति) तो पहले और दूसरे अंक के बीच एक अल्पविराम डाला जाना चाहिए।

उदाहरण के लिए,

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, ताकि वह वापस कूद जाए।

यहाँ एक बश डेमो ( 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 से बैकस्लैश न्यूलाइन आउटपुट निकालने की आवश्यकता है । यह संख्या बहुत बड़ी है, जो जागने में फ्लोट या निश्चित बिट संख्या के रूप में माना जाता है, और मैं यह भी नहीं चाहता कि बड़े पैमाने पर सभी अंकों के लिए एक रेक्सएक्सपी का निर्माण किया जाए। इसके बजाय, मैं इसे उल्टा कर सकता हूं और तीन अंकों के समूहों के बीच अल्पविराम लगा सकता हूं, फिर इसे हटा दें:

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 और डेबियन-आधारित वितरणों पर आपके उदाहरण की कोशिश की, लेकिन सभी मामलों में, बड़ी संख्या में Awk को कोई समस्या नहीं थी। मैंने इसके बारे में कुछ और सोचा और यह मेरे लिए हुआ कि मैंने जिन सभी प्रणालियों पर प्रयोग किया था वे 64-बिट (यहां तक ​​कि एक बहुत पुराना वीएम चल रहा है असमर्थित आरएचईएल 5)। यह तब तक नहीं था जब तक कि मैं 32-बिट ओएस पर चलने वाले एक पुराने लैप-टॉप का परीक्षण नहीं करता, जिसे मैं आपके मुद्दे को दोहराने में सक्षम था awk: run time error: improper conversion(number 1) in printf("%'d:।
एंथनी जी -

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. से अधिक हो तो एक शानदार अग्रणी अल्पविराम जुड़ जाता है
स्टीफन चेज़लस

@ स्टीफनचेज़ेलस: आप उस अंतिम रीव कमांड के आउटपुट को ले सकते हैं, और उसे पाइप कर सकते हैं sed 's/^,//g'
TSJNachos117

0

मैं भी भाग करना चाहते थे के बाद दशमलव विभाजक सही ढंग से अलग हो / स्थान दिया गया है, इसलिए मैं इस 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'
}

0

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अंतराल रेगेक्स ऑपरेटरों का समर्थन नहीं करते हैं, regexp को बदल दें/(^|[^.0123456789])[0123456789][0123456789][0123456789][0123456789]+/

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.