'Sed' के साथ जोड़


40

मैं एक गणितीय ऑपरेशन करने की कोशिश कर रहा हूं sed, लेकिन यह मेरे चर को तार के रूप में मानता है। इनपुट इस प्रकार है:

$ echo 12 | sed 's/[0-9]*/&+3/'
$ 12+3

मुझे आउटपुट के रूप में 15 चाहिए। मुझे ऑपरेशन करने और इसके गणितीय परिणाम को केवल एक ही मार्ग में बदलने की आवश्यकता है, क्योंकि मैं पायथन डेमॉन के रूप में कार्यक्रम चला रहा हूं, और मैं stdoutफाइलों पर पुनर्निर्देशन जैसे मार्ग से बचना चाहता हूं , उन फाइलों को खोलना, ऑपरेशन करना, परिणाम निकालना, करना प्रतिस्थापन। मेरे लिए, sedसभी को एक पंक्ति में करना सबसे अच्छा लगता है।

मैंने इनपुट और आउटपुट दोनों तरह से डालने की कोशिश की है

$ echo 12 | sed 's/[0-9]*/int(&+3)/'
$ echo 12 | sed 's/[0-9]*/\int(&+3)/'
$ echo 12 | sed 's/[0-9]*/\int(&+3)/'

लेकिन परिणाम हमेशा दूसरे क्षेत्र की छपाई का था।


12
यह आपके "वैरिएबल" को स्ट्रिंग्स के रूप में मान रहा है क्योंकि यह सब सेड है - स्ट्रिंग हेरफेर। इसमें "पूर्णांक" की कोई अवधारणा नहीं है।
केविन

2
मैं बहुत उत्सुक हूं कि आप sedगणित करने के लिए क्यों इस्तेमाल करना चाहते हैं
डेविड वनिल

मैंने सोचा था कि यह आसानी से चर डाल सकता है, एहसास नहीं था कि यह कितना जटिल था!
लुइगी टिबुरज़ी

जवाबों:


82

यदि आप ईमानदारी से sed का उपयोग करना चाहते हैं, तो यह जाने का तरीका है:

s/[0-9]/<&/g
s/0//g; s/1/|/g; s/2/||/g; s/3/|||/g; s/4/||||/g; s/5/|||||/g; s/6/||||||/g
s/7/|||||||/g; s/8/||||||||/g; s/9/|||||||||/g
: tens
s/|</<||||||||||/g
t tens
s/<//g
s/+//g
: minus
s/|-|/-/g
t minus
s/-$//
: back
s/||||||||||/</g
s/<\([0-9]*\)$/<0\1/
s/|||||||||/9/; s/||||||||/8/; s/|||||||/7/; s/||||||/6/; s/|||||/5/; s/||||/4/
s/|||/3/; s/||/2/; s/|/1/
s/</|/g
t back

इनपुट:

1+2
100+250
100-250

आउटपुट:

3
350
-150

अपने मिशन, आप इसे स्वीकार करने के लिए चुनना चाहिए, गुणा लागू करना है।


5
चुनौती के लिए +1, इसे प्यार करो! हो सकता है कि कोड गोल्फ के लिए कुछ होगा ;
तातजाना हेसर

6
और कुछ लोग कहते हैं कि प्रोग्रामिंग गणित नहीं है। यह छोटा रत्न उन सभी का खंडन करता है। बेस 1 का सबसे अच्छा उपयोग।
ब्रूस एडगर

1
अच्छा है! - @ साइमन: मैं आपको चुनौती देता हूं कि आप टेट्रेशन लागू करें : P
AT

16
+1 यह एक सुंदर उदाहरण है कि रचनात्मकता के साथ गलतफहमी क्या हो सकती है।
रोज़ज़ेट्रिएवेज़ेज़

1
गुणा सेड के साथ किया जाता है - और यह बहुत अच्छी तरह से बड़ी संख्या में होता है!
टोबे स्पाइट

20

sedयहाँ सबसे अच्छा विकल्प नहीं है, यह मूल रूप से अंकगणित नहीं करता है (देखें कि आप संभवतः इसे कैसे कर सकते हैं, इसके लिए एक संख्या बढ़ाएँ )। आप ऐसा कर सकते हैं awk:

$ echo 12 | awk '{print $0+3}'
15

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

आप भी केवल इसके साथ कर सकते हैं bash:

$ echo $(( $(echo 12) + 3 ))

या exprएक समान फैशन में उपयोग कर ।


17

मैंने आपकी चुनौती को स्वीकार करने का प्रयास किया

sed 's/[0-9]/<&/g
s/0//g; s/1/|/g; s/2/||/g; s/3/|||/g; s/4/||||/g; s/5/|||||/g; s/6/||||||/g
s/7/|||||||/g; s/8/||||||||/g; s/9/|||||||||/g
: tens
s/|</<||||||||||/g
t tens
s/<//g
s/.*\*$/0/
s/^\*.*/0/
s/*|/*/
: mult
s/\(|*\)\*|/\1<\1*/ 
t mult
s/*//g
s/<//g
: back
s/||||||||||/</g
s/<\([0-9]*\)$/<0\1/
s/|||||||||/9/; s/||||||||/8/; s/|||||||/7/; s/||||||/6/; s/|||||/5/; s/||||/4/
s/|||/3/; s/||/2/; s/|/1/
s/</|/g
t back'

इनपुट:

04*3
4*3
40*3
42*32
150*20
1*3
3*1
0*3
3*0

आउटपुट: सभी सही परिणाम


@SimonRichter आशा है कि आप आनंद लेंगे !!
लुइगी टिबुरज़ी

क्रॉस ने इस शानदार उत्तर को यहां पोस्ट किया: codegolf.stackexchange.com/a/39882/11259
डिजिटल ट्रॉमा

12

perlकाफ़ी मिलती-जुलती निर्माण के लिए अनुमति देता sedहै ... एक अंतर यह है कि है perlऔर अधिक जटिल कर सकते हैं ... sedसाधारण पाठ substitions के लिए बहुत अच्छा है

 echo 'a12' | perl -pe 's/([0-9]+)/($1+3)/e'  # the trailing /e means evaluate

उत्पादन

a15

2
कैप्चरिंग कोष्ठक के बिना भी कर सकते हैं:perl -pe 's/[0-9]+/$&+3/e'
ग्लेन जैकमैन


6

मुझे वास्तव में यह स्वीकार नहीं है कि स्वीकार किए गए उत्तर की चरम जटिलता, या तो नीचे दी गई बात पर आप क्या चाहते हैं:

echo 12 | sed 's/[0-9]*/echo \$(( & + 3 ))/e'

या

echo 12 | sed 's/[0-9]*/expr & + 3/e'

मुझे लगता है कि इसे GNU sed की आवश्यकता हो सकती है, लेकिन मुझे यकीन नहीं है।


यह एक गानु विस्तार है।
केविन

ठीक है, आप सही हैं, लेकिन जवाब आगे निकल जाता है, यह सामान्य जोड़ को एक विशेष रूप से लागू करता है, आप किसी भी दो नंबरों को खिला सकते हैं और आपको परिणाम मिलेगा
लुइगी टिबुरज़ी

@LuigiTiburzi "x + y" शैली इनपुट के लिए इसे सामान्य करने के लिए काफी सरल है:echo 12+3 | sed -r 's/([0-9]*) *\+ *([0-9]*)/expr \1 + \2/e'
डिजिटल ट्रॉमा

5

यदि आपको निश्चित रूप से नियमित अभिव्यक्ति और अंकगणितीय संचालन को संयोजित करना है, तो ऐसी भाषा चुनें जहां नियमित अभिव्यक्ति के प्रतिस्थापन पैरामीटर एक कॉलबैक फ़ंक्शन हो सकता है।

पर्ल, रूबी, जावास्क्रिप्ट और पायथन ऐसी भाषाएँ हैं:

bash-4.2$ echo 12 | perl -pe 's/\d+/$&+3/e'
15

bash-4.2$ echo 12 | ruby -pe '$_.sub!(/\d+/){|s|s.to_i+3}'
15

bash-4.2$ echo 12 | js -e 'print(readline().replace(/\d+/,function(s){return parseInt(s)+3}))'
15

bash-4.2$ echo 12 | python -c 'import re;print re.sub("\d+",lambda s:str(int(s.group(0))+3),raw_input())'
15

1

एक और सरल bashउपाय, जो वास्तव में एक पाइप में काम करता है:

 echo 12 | { read num; echo $(( num + 3)); }

1

यदि आप कुछ बाशिस्म में मिश्रण करते हैं:

echo $(($(echo 12 | sed 's/[0-9]*/&+3/')))

पाठ से संख्या निकालने के लिए:

echo $(($(echo "foo12bar" | sed -r 's/[^0-9]*([0-9]*).*/\1+3/')))

बिना सेड, बस बैश:

var="foo12bar"
echo $((${var//[^0-9]/}+3))

हर गैर-अंक को प्रतिस्थापित ${var//[^0-9]/}करता है और डबल राउंड पार्न्स में अंकगणित करता है:$((x+3))


2
वहां कोई बैशीवाद नहीं है। $((...))POSIX द्वारा शुरू किया गया था (bashism है $[...])। ${var//xxx/x}zsh और bash द्वारा कॉपी की गई एक kshism भी है। sed -rएक GNUism है
स्टीफन चेज़लस

0

यहाँ एक पर्ल समाधान है:

echo 12 | perl -wlpe '$_ += 3'
# Output:  15

यदि आप एक स्ट्रिंग में अंकित अंकों के पहले सेट को बदलना पसंद करते हैं, तो आप इसका उपयोग कर सकते हैं:

echo I am 12 years old. | perl -wlpe 's/(\d+)/$1 + 3/e'
# Output:  I am 15 years old.

यदि आप किसी स्ट्रिंग में अंकों के सभी सेटों को बदलना पसंद करते हैं , तो आप /gइस तरह से संशोधक का उपयोग कर सकते हैं :

echo They are 11, 12, and 13 years old. | perl -wlpe 's/(\d+)/$1 + 3/eg'
# Output:  They are 14, 15, and 16 years old.

0

हालांकि sed अभिव्यक्ति का उपयोग करना महान है, इसकी सीमाएं हैं। उदाहरण के लिए निम्नलिखित विफल रहता है:

$ echo "1000000000000000000000000000000+1" | sed -e 's/\([0-9]*\)+\([0-9]*\)/expr \1 + \2/e'
expr: 1000000000000000000000000000000: Numerical result out of range

इस सीमा को पार करने के लिए मेरा एक सिंपल पॉवर ऑफ सेड में बदल जाता है और मनमानी लंबाई दशमलव योजक के बाद लागू होता है:

#! / बिन / sed -f

रों / + / \ N / जी
एस / $ / \ n \ N0 /

: लूप
s / ^ \ (। * \) \ (। \) \ n \ (। * \) \ (। \) \ n \ (। * \) \ n \ (। \) $ / 0 \ 1 \ N0 \ 3 \ n \ 5 \ n \ 6 \ 2 \ 4 /
ज
रों /^.* \ N। * \ N। * \ n \ (... \) $ / \ 1 /

# दशमलव पूर्ण योजक मॉड्यूल
# INPUT: 3digits (कैरी इन, ए, बी,)
# आउट: 2 बिट्स (कैरी, सम)
एस / $ /;000 = 00001 = 01002 = 02003 = 03004 = 04005 = 05006 = 06007 = 07008 = 08009 = 09010 = 01011 = 02012 = 03013 = 04014 = 05015 = 06016 = 07017 = 08018 = 09019 = 10020 = 02021 = 03022 = 04023 = 05024 = 06025 = 07026 = 08027 = 09028 = 10029 = 11030 = 03031 = 04032 = 05033 = 06034 = 07035 = 08036 = 09037 = 10038 = 11039 = 12040 = 04041 = 05042 = 06043 = 07044 = 08045 = 09046 = 10047 = 11048 = 12049 = 13050 = 05051 = 06052 = 07053 = 08054 = 09055 = 10056 = 11057 = 12058 = 13059 = 14060 = 06061 = 07062 = 08063 = 09064 = 10065 = 11066 = 12067 = 13068 = 14069 = 15070 = 07071 = 08072 = 09073 = 10074 = 11075 = 12076 = 13077 = 14078 = 15079 = 16080 = 08081 = 09082 = 10083 = 11084 = 12085 = 13086 = 14087 = 15088 = 16089 = 17090 = 09091 = 10092 = 11093 = 12094 = 13095 = 14096 = 15097 = 16098 = 17099 = 18100 = 01101 = 02102 = 03103 = 04104 = 05105 = 06106 = 07107 = 08108 = 09109 = 10110 = 02111 = 03112 = 04113 = 05114 = 06115 = 07116 = 08117 = 09118 = 10119 = 11120 = 03121 = 04122 = 05123 = 06124 = 07125 = 08126 = 09127 = 10128 = 11129 = 12130 = 04131 = 05132 = 06133 = 07134 = 08135 = 09136 = 10137 = 11138 = 12139 = 13140 = 05141 = 06142 = 07143 = 08144 = 09145 = 10146 = 11147 = 12148 = 13149 = 14150 = 06151 = 07152 = 08153 = 09154 = 10155 = 11156 = 12157 = 13158 = 14159 = 15160 = 07161 = 08162 = 09163 = 10164 = 11165 = 12166 = 13167 = 14168 = 15169 = 16170 = 08171 = 09172 = 10173 = 11174 = 12175 = 13176 = 14177 = 15178 = 16179 = 17180 = 09181 = 10182 = 11183 = 12184 = 13185 = 14186 = 15187 = 16188 = 17189 = 18190 = 10191 = 11192 = 12193 = 13194 = 14195 = 15196 = 16197 = 17198 = 18199 = 19 /
s / ^ \ (... \) [^;] * [^;]। * \ 1 = \ (.. \) * / \ 2 /
एच
जी
s / ^ \ (। * \) \ n \ (। * \) \ n \ (। * \) \ n ... \ n \ (। \) \ (। \) $ / \ 1 \ n \ 2 \ n \ 5 \ 3 \ n \ 4 /
/ ^ \ ([0] * \ _ \ n \ _ ([0] * \ _) \ n / {
        रों /^.* \ N। * \ n \ (। * \) \ n \ (। \) / \ 2 \ 1 /
        s / ^ 0 \ (। * \) / \ 1 /
        क्ष
}
बी LOOP

जिस तरह से यह काम करता है वह दशमलव योजक मॉड्यूल को लागू करने से होता है जो दो इनपुट अंकों (ए और बी) के साथ-साथ कैरी बिट को जोड़ता है और एक सम और कैरी बिट का उत्पादन करता है। इस विचार को इलेक्ट्रॉनिक से उधार लिया गया है जहां बाइनरी एडिटर बाइनरी नंबर के लिए एक ही करता है। हमें बस इतना करना है कि सभी अंको के साथ जोड़ को कम करना है और हम मनमाने ढंग से लंबाई की संख्या (मेमोरी द्वारा सीमित) जोड़ सकते हैं। नीचे कार्रवाई में योजक है:

./decAdder.sed
666666666666666666666666666666999999999999991111111112222+1100000000000000000000011111111111111111111111111111111111
1766666666666666666666677777778111111111111102222222223333

ठीक उसी तरह जैसे कोई भी बाइनरी (या किसी अन्य आधार) योजक को लागू कर सकता है। आपको बस उस पंक्ति को बदलना है जो s/$/;000=00001...आधार के लिए उचित प्रतिस्थापन पैटर्न के साथ शुरू होती है । उदाहरण के लिए: s/$/;000=00001=01010=01011=10100=01101=10110=10111=11/ मनमाना लंबाई बाइनरी योजक के लिए प्रतिस्थापन पैटर्न है।

आप मेरे जीथूब पर प्रलेखित कोड को फिट कर सकते हैं ।

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