रेगेक्स एंड सेड / पर्ल: मैच शब्द जो ISN'T एक और शब्द से पहले था


11

मैं किसी ऐसे शब्द की सभी घटनाओं का उपयोग करना sedया perlप्रतिस्थापित करना चाहता हूं जिसके सामने एक निश्चित शब्द नहीं है।

उदाहरण के लिए, मेरे पास एक पाठ फ़ाइल है जिसमें एक मूवी का एक प्लॉट होता है और मैं किसी चरित्र के अंतिम नाम की सभी घटनाओं को उनके पहले नाम से बदलना चाहता हूं, लेकिन केवल अगर उनका पहला नाम उनके अंतिम नाम से पहले नहीं आता है।

नमूना पाठ इस तरह दिख सकता है:

John Smith and Jane Johnson talk about Smith's car.

मैं चाहता हूं कि यह इस तरह दिखे:

John Smith and Jane Johnson talk about John's car.

अगर मैं बस करता sed 's/Smith/John/' file, तो मैं होता:

John John and Jane Johnson talk about John's car.

पहला नाम जो अंतिम नाम से पहले आता है वह हमेशा एक ही होगा। मैं के साथ सौदा नहीं है John Smithऔर Frank Smith। मुझे मैच करने का एक तरीका Smithचाहिए Johnजो इसे पहले से न हो ।


आप किस सेड की बात कर रहे हैं?
इग्नासियो वाज़केज़-अब्राम्स

लिनक्स पर GNU sed 4.2.1
jonescb

जवाबों:


8

किसी भी भाषा के साथ आसान होगा जहां नियमित अभिव्यक्तियाँ देखने में सक्षम हैं। बेशक, पर्ल सूची में पहले स्थान पर है:

perl -pe 's/(?<!John\W)Smith/John/g' <<< "John Smith and Jane Johnson talk about Smith's car."

कमजोर बिंदु "जॉन" और "स्मिथ" के बीच एक से अधिक गैर-शब्द चरित्र है। दुर्भाग्य की तरह एक परिमाणक +के लिए \Wउठाएंगे त्रुटि "चर लंबाई लागू नहीं किया lookbehind"।


6

EDIT .. अपनी टिप्पणी पुनः दें .. यहाँ एक नई स्क्रिप्ट है जो अपने आप में चिंता का विषय नहीं है (उदाहरण के लिए) विलियम स्मिथ। यह अस्थायी रूप से पैटर्न को बाधित करता है जो इसे स्मिथ (अपरिवर्तित) के रूप में रखता है ।

sed -r 's/\<(John) (Smith)\>/\1\x01x\2/g; 
        s/\<Smith\>/John/g;  s/\x01x/ /g'

यदि आप श्रीमान श्रीमती के बारे में चिंतित हैं ... तो यह काम करता है।

sed -r 's/\<(John|((M(r|rs|s))\.?)) (Smith)\>/\1\x01x\5/g
        s/\<Smith\>/John/g; s/\x01x/ /g'

आप विलियम का नाम या सूची में उनका नाम जोड़कर पूरा कर सकते हैं , जैसे।
sed -r 's/\<(William|John|...


यह मूल लिपि है

sed -r 's/(^|[[:punct:]] |\<[a-z]+ )(Smith\>)/\1John/'

यह काम करता है, लेकिन मुझे जो एक समस्या मिली वह यह थी कि अगर स्मिथ से पहले के शब्द को कैपिटल किया गया है (जैसे कि यह एक वाक्य में पहले शब्द के बाद आता है) तो यह मेल नहीं खाता। मैनेटवर्क द्वारा पर्ल के समाधान में वह समस्या नहीं है, भले ही वह अन्य स्थितियों में विफल हो। सौभाग्य से, मेरी पाठ फ़ाइल में श्री या समान अंतिम नाम वाले लोग जैसे शीर्षक नहीं हैं।
jonescb

हाँ धन्यवाद ... मैंने एक संशोधित स्क्रिप्ट पोस्ट की है ...
20

1
 sed -r 's/([^John] )Smith/\1John/g;s/([^Jane] )Johnson/\1Jane/g'

() एक LastName से पहले नॉन-फर्स्टनेम पर कब्जा कर लेगा, इसलिए वे प्रतिस्थापन में वापस आ जाएंगे।

संपादित करें

@ Manatwork, गाइल्स

आप सही हे। कैसा रहेगा

sed -r 's/(John Smith)/temp1/g;s/Smith/John/g;s/temp1/John Smith/g'

इस चाल को करने के लिए लगता है।


यह विफल हो जाएगा अगर नाम के आगे कोई दूसरा शब्द नहीं है, उदाहरण के लिए "स्मिथ और जेन जॉनसन स्मिथ की कार के बारे में बात करते हैं।"
manatwork

2
[^John]एक चरित्र, जिनमें से एक होना चाहिए से मेल खाता है J, o, hया n। मुझे संदेह है कि आपका इरादा क्या है। नियमित अभिव्यक्तियों में कोई नकारात्मक निर्माण नहीं है (पर्ल के पास (?!…)और है (?<!…), लेकिन अगर आप इसे नकारात्मक मानते हैं, तो यह संभवतः वह नहीं करेगा जो आप उम्मीद करते हैं)।
गिलेस एसओ-

@ जूको: आपका टेक -2 काम करता है, लेकिन अप्रत्याशित डेटा के लिए अतिसंवेदनशील है। मैंने एक समान विधि का उपयोग किया (यद्यपि थोड़ा अनिच्छा से) क्योंकि sedबिना इसके उपयोग से फूला हुआ सेड लॉजिक बनता है ... temp1लगभग हमेशा ठीक रहेगा, लेकिन! उस बस के लिए बाहर देखो। इस संभावना को कम करने के लिए, मेरा मानना ​​है कि उन वर्णों का उपयोग करना बेहतर है जो (लगभग) लैटिन-स्क्रिप्ट पाठ फ़ाइलों में कभी नहीं होते हैं, जैसे हेक्स मान \ x01 \ x02, या उनमें से संयोजन, या शायद \ xe188b4 UTF-8ale (ሴ -) प्राचीन सांकेतिक दृश्य) .. उदा। echo -e 'Z' |sed 's/./\xe1\x88\xb4/'=> जब लोकेल UTF-8 है ..
पीटर.ओ.
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.