एक स्ट्रिंग में स्थिति के आधार पर अग्रणी शून्य के एक चर संख्या को जोड़ने के लिए एक विस्तारित regexp को लागू करना


10

मैं एक संख्यात्मक संगठनात्मक योजना के लिए अग्रणी शून्य की एक अलग संख्या जोड़ने के लिए मेरे sed सिंटैक्स को प्राप्त करने में परेशानी हो रही है। मैं जिस स्ट्रिंग्स पर काम कर रहा हूं, वह ऐसा प्रतीत होता है

1.1.1.1,Some Text Here

sed सिंटैक्स का लाभ उठाना

sed -r ":r;s/\b[0-9]{1,$((1))}\b/0&/g;tr"

मैं प्रतिक्रिया को प्राप्त करने में सक्षम हूं

01.01.01.01,Some Text Here

हालाँकि, मैं जिस चीज़ की तलाश कर रहा हूँ, वह 2 से 2 अंकों के शून्य को भरने के लिए कुछ है 2 और 3 और 3 के क्षेत्र में 4 अंक ताकि सभी आइटम एक मानक लंबाई के हैं [0-9] [0-9] { 2}। [0-9] {2}। [0-9] {3}

1.01.01.001,Some Text Here

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

sed -r ":r;s/\.\b[0-9]{1,$((1))}\b/0&/g;tr"
sed -r ":r;s/\b\.[0-9]{1,$((1))}\b/0&/g;tr"
Both cause the statement to hang

sed -r ":r;s/\b[0-9]\.{1,$((1))}\b/0&/g;tr"
sed -r ":r;s/\b[0-9]{1,$((1))}\.\b/0&/g;tr"
sed -r ":r;s/\b[0-9]{1,$((1))}\b\./0&/g;tr"
cause the statement to output:

1.01.01.1,Some Text Here

इसके अतिरिक्त, मुझे उम्मीद है कि यदि वक्तव्य में पाठ शामिल है तो मुझे अतिरिक्त समस्याएं होंगी:

1.1.1.1,Some Number 1 Here

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

संपादित करें: मैंने एक तरीका निकाला है ... यह कथन वह है जो मैं देख रहा हूँ, लेकिन ऐसा करने के लिए एक और अधिक सुंदर तरीका होना चाहिए।

sed -r ':r;s/\b[0-9]{1,1}\.\b/0&/;tr;:i;s/\b[0-9]{1,2},\b/0&/;ti;s/.//'

इसके अलावा, यदि पाठ में एक समान संख्या स्वरूप दिखाई देता है, तो भी यह वाक्यगत रूप से समस्या उत्पन्न करेगा ... के समान:

1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3

किस स्थिति में इसका परिणाम होगा:

1.01.01.001,Some Text Referring to Document XXX Heading 01.02.03

हल यहाँ आपकी मदद के लिए आप सभी को धन्यवाद। मैंने शुरू में नीचे दिए गए उत्तर के साथ समस्या को हल किया। मुझे लगता है कि पायथन में समाधान को एक बड़े समाधान के एक भाग के रूप में नीचे ले जाने के रूप में ले जाया गया है:

def getPaddedKey(line):
    keyparts = line[0].split(".")
    keyparts = map(lambda x: x.rjust(5, '0'), keyparts)
    return '.'.join(keyparts)

s=sorted(reader, key=getPaddedKey)

ऐसा लगता है कि मैं क्या देख रहा हूं: sed -r ':r;s/\b[0-9]{1,1}\.\b/0&/;tr;:i;s/\b[0-9]{1,2},\b/0&/;ti;s/.//' हालांकि, मुझे यह जानना अच्छा लगेगा कि क्या अधिक सुरुचिपूर्ण दृष्टिकोण है।
डेविज़ाई

1
अजीब तरह से, स्ट्रिंग को उल्टा करना, अनुगामी शून्य को लागू करना , और फिर परिणाम को उलटने से आपका लक्ष्य अधिक आसानी से प्राप्त हो सकता है।
1848 में 1848 में रोएमा

2
प्रयोग printf(या printfअक्क के भीतर एक कॉल) अधिक सीधा हो सकता है।
वाइल्डकार्ड

1
यह निश्चित रूप से ऐसी चीज है जो भविष्य में awk या perl (या कुछ और जिसमें प्रिंटफ और आसान फील्ड-विभाजन है) को लागू करना, पढ़ना, समझना और संशोधित करना आसान होगा।
कैस

1
@Wildcard - बिंदु अच्छी तरह से लिया। क्या आप मुझे डीबगिंग सेड के बारे में कुछ बता सकते हैं? आमतौर पर, मैं लंबे समय तक अभिनय से लंबे समय तक घूरने का सहारा लेता हूं। ;) इस बात पर रोक लगाते हुए कि, मैं कभी-कभी एक सेड स्टेटमेंट को छोटे टुकड़ों में तोड़ता हूं और फिर से संयोजन करने से पहले प्रत्येक को काम पर लाने की कोशिश करता हूं। मैंने हाल ही में एक महान ट्यूटोरियल पढ़ा github.com/learnbyexample/Command-line-text-processing/blob/… और मुझे यकीन है कि कुछ उदाहरण गलत थे जब तक कि मैंने लंबे समय तक घूर नहीं लगाया।
जो

जवाबों:


4

उपयोग: leading_zero.sh input.txt

#!/bin/bash

sed -r '
    s/\.([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{1,3},)/.0\1.0\2.00\3/
    s/\.0*([0-9]{2})\.0*([0-9]{2})\.0*([0-9]{3})/.\1.\2.\3/
' "$1"

स्पष्टीकरण:

  1. पहले घटाव प्रत्येक संख्या में शून्य की निश्चित मात्रा को जोड़ते हैं। 1 शून्य से 2 और 3 संख्या, 2 शून्य से 4 संख्या। इससे कोई फर्क नहीं पड़ता कि पहले से कितने अंक हैं।
  2. दूसरा विकल्प सभी अतिरिक्त शून्य को हटाता है, केवल आवश्यक संख्याओं को छोड़ता है। 2 और 3 संख्याओं में केवल 2 अंक होने चाहिए। उन्हें छोड़ देता है और आराम करता है। चौथे नंबर में केवल 3 अंक होने चाहिए। उन्हें छोड़ देता है और आराम करता है।

input.txt

1.1.1.1,Some Text Here
1.1.1.1,Some Text Here
1.11.1.11,Some Text Referring to Document XXX Heading 1.2.3
1.1.1.1,Some Text Here
1.1.11.111,Some Text Referring to Document XXX Heading 1.2.3
1.11.1.1,Some Text Here

output.txt

1.01.01.001,Some Text Here
1.01.01.001,Some Text Here
1.11.01.011,Some Text Referring to Document XXX Heading 1.2.3
1.01.01.001,Some Text Here
1.01.11.111,Some Text Referring to Document XXX Heading 1.2.3
1.11.01.001,Some Text Here

हालांकि अंत में मैंने पायथन में इसे स्क्रिप्टिंग के लिए समाप्त कर दिया। यह 1. एक sed समाधान है, और 2. पाठ के छेड़छाड़ के बिना उचित उत्पादन का उत्पादन करता है। उत्तर के रूप में चिह्नित करना। धन्यवाद! :-)
दैइजई

@ दाइजीजई जैसा कि मैंने पहले ही प्रदर्शित किया है, perlसंस्करण बैकस्लैश को नहीं हटाता है।
रोइमा

9

बैश इसे संभाल सकता है। हालांकि यह पर्ल की तुलना में बहुत धीमा होगा:

echo "1.1.1.1,Some Text Here" | 
while IFS=., read -r a b c d text; do
    printf "%d.%02d.%02d.%03d,%s\n" "$a" "$b" "$c" "$d" "$text"
done
1.01.01.001,Some Text Here

2
या अवाक्। लेकिन उपयोग करने के लिए +1 printf, समझदार उपकरण। (अक्क में टेक्स्ट प्रोसेसिंग के लिए printfभी बेहतर तरीके से डिज़ाइन किया गया है bash।) यह भी देखें कि टेक्स्ट को प्रोसेस करने के लिए शेल लूप का उपयोग करना बुरा व्यवहार क्यों माना जाता है?
वाइल्डकार्ड

5

आपने विशेष रूप से एक perlसमाधान के लिए नहीं कहा है, लेकिन यहाँ एक वैसे भी है। व्यक्तिगत रूप से मुझे लगता है कि यह पढ़ना थोड़ा आसान है, खासकर जब कई लाइनों में टूट गया हो।

पहले यहाँ एक लाइनर है:

(
    echo '1.2.3.4,Some Text Here'
    echo '1.01.01.1,Some Text Here'
    echo '1.1.1.1,Some Number 1 Here'
    echo '1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3'
    echo '1.2.3.4,Some \n \s \text'
) |
perl -ne '($ip, $text) = split(/,/, $_, 2); $ip = sprintf("%1d.%02d.%03d.%03d", split(/\./, $ip)); print "$ip,$text"'

इसके परिणाम:

1.02.003.004,Some Text Here
1.01.001.001,Some Text Here
1.01.001.001,Some Number 1 Here
1.01.001.001,Some Text Referring to Document XXX Heading 1.2.3
1.02.003.004,Some \n \s \text

और यहां perlस्क्रिप्ट को तोड़ दिया गया और टिप्पणी की गई ( -nध्वज while read; do ... doneकोड के चारों ओर एक अंतर्निहित लूप डालता है ):

($ip, $text) = split(/,/, $_, 2);                # Split line into two parts by comma
@octets = split(/\./, $ip)                       # Split IP address into octets by dots
$ip = sprintf("%1d.%02d.%03d.%03d", @octets);    # Apply the formatting
print "$ip,$text"                                # Output the two parts

विडंबना यह है कि जब आप इसे पोस्ट करते थे, तो मैं इसे सेड में छोड़ देता था और जागने के लिए कदम बढ़ाता था। यह बिल फिट करने के लिए लगता है। मैं इसकी जाँच करूँगा और वापस आ जाऊँगा।

@daijizai awkभी काम करेगा - उसी सिद्धांत का उपयोग करprintf
roaima

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

@daijizai यहाँ नहीं यह नहीं है। आप इसे बैकस्लैश के साथ पाठ कैसे खिला रहे हैं? मैंने आपके लिए एक
बैकस्लेस्ड

मेरे आंतरिक डेटासेट के साथ मेरे उपयोग में कुछ टेक्स्ट कॉलम हैं, जिनमें कुछ स्ट्रिंग जैसे SOME \ Text \ Might \ Be \ Here \ 4Rzz हैं। जब इस डेटासेट को पर्ल स्टेटमेंट में पास किया गया तो इसके परिणामस्वरूप SOMETextMightBeHere4Realz जैसी प्रतिक्रिया हुई
daijizai

3

यहाँ एक संभव दृष्टिकोण है:
sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'

उदाहरण

echo "1.11.111.1111,Some Text Here" | sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'
1.011.0111.001111,Some Text Here

इस तार के साथ भी काम करें:

echo "1.1.1.1,Some Number 1 Here" | sed -E 's/([0-9]\.)/0\1/g;s/.//;s/([0-9],)/00\1/'
1.01.01.001,Some Number 1 Here

... और यह तार:

echo "1.2.2101.7191,Some Text Here" | sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'
1.02.02101.007191,Some Text Here

दुर्भाग्य से यह टूट जाता है क्योंकि अंक चढ़ते हैं। उदाहरण के लिए: १.१.११.१११, कुछ पाठ यहाँ बने: १.१.१०१.११००१, कुछ पाठ यहाँ
१iz:१

@daijizai कृपया मेरा संपादन देखें। क्या यह आवश्यकता को पूरा करेगा?
माउलिंग्लॉन्स

दुर्भाग्य से नहीं, लेकिन मुझे लगता है कि मेरी गलती हो सकती है। शून्य-भरण की आवश्यकता फ़ील्ड 2 पर 2 दो और 3 और 3 अंक 3 फ़ील्ड पर होने की आवश्यकता है। अनिवार्य रूप से [0-9] [0-9] {2}। [0-9] {2}। [0 -9] {3}, कुछ पाठ यहाँ
daijizai

2
perl -pe '/^\d/g && s/\G(?:(\.\K\d+(?=\.))|\.\K\d+(?=,))/sprintf "%0".($1?2:3)."d",$&/ge'

स्पष्टीकरण:

इस पद्धति का उपयोग यहां संख्यात्मक रूप से पड़ोस को देखने और उसके आधार पर कार्रवाई करने के लिए किया जाता है। तो, दूसरे और तीसरे नंबर पर दोनों तरफ एक डॉट दिखाई देता है, जबकि 4 के सांख्यिक डॉट पर बाईं ओर डॉट और दाईं ओर एक अल्पविराम होता है।

$ 1 तब सेट किया जाता है जब रेगेक्स 2 या 3 अंक का पथ लेता है और तदनुसार सटीक पैडिंग 2 है। ओटीओएच, 4 वें नंबर के लिए, पैडिंग 3 है।

% cat file.txt

1.00.3.4,Some Text Here
1.01.01.1,Some Text Here
1.0.01.1,Some Number 1 Here
1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3.4
1.2.3.4,Some \n \s \text

परिणाम:

1.00.03.004,Some Text Here
1.01.01.001,Some Text Here
1.00.01.001,Some Number 1 Here
1.01.01.001,Some Text Referring to Document XXX Heading 1.2.3.4
1.02.03.004,Some \n \s \text
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.