पाठ फ़ाइल में प्रतिस्थापन ** बिना ** नियमित अभिव्यक्ति


68

मुझे प्रतिस्थापन के साथ एक पाठ फ़ाइल के अंदर कुछ पाठ को प्रतिस्थापित करने की आवश्यकता है। आमतौर पर मैं ऐसा कुछ करता

sed -i 's/text/replacement/g' path/to/the/file

समस्या यह है कि दोनों textऔर replacementजटिल तार हैं जिनमें डैश, स्लैश, ब्लैकस्लैश, उद्धरण और इतने पर हैं। अगर मैं textचीज के अंदर सभी आवश्यक पात्रों से बच जाता हूं, तो जल्दी से अपठनीय हो जाता है। दूसरी ओर मुझे नियमित अभिव्यक्ति की शक्ति की आवश्यकता नहीं है: मुझे केवल पाठ को शाब्दिक रूप से प्रतिस्थापित करने की आवश्यकता है।

क्या कुछ बैश कमांड के साथ नियमित अभिव्यक्ति का उपयोग किए बिना पाठ प्रतिस्थापन करने का एक तरीका है ?

यह एक स्क्रिप्ट लिखने के लिए तुच्छ होगा जो ऐसा करता है, लेकिन मुझे लगता है कि पहले से ही कुछ मौजूद होना चाहिए।


बैश के माध्यम से करना आवश्यक है? एक सरलीकृत समाधान वर्ड में खोलना और एकfind and replace all
आकाश

17
@ आकाश क्योंकि bashमाइक्रोसॉफ्ट वर्ड के साथ हमेशा शिप करने वाले सिस्टम ? ;) बस मजाक कर रहा था। ओपी एक दूरस्थ मशीन पर या फ़ाइलों के एक बैच के लिए ऐसा करना चाह सकता है।
15

@ एसएलएचके :) ठीक है, मुझे लगता है कि जीएडिट का एक समान विकल्प होना चाहिए
आकाश

एक विकल्प यह होगा कि किसी भी चीज को सही तरीके से पास करने से पहले वह बच जाए sed, जो कि संभवत: सभी स्विच और प्लेटफॉर्म के अंतर को देखते हुए एक निरर्थक प्रयास है।
l0b0

जवाबों:


6

जब आपको नियमित अभिव्यक्ति की शक्ति की आवश्यकता नहीं होती है, तो इसका उपयोग न करें। यह ठीक है।
लेकिन, यह वास्तव में एक नियमित अभिव्यक्ति नहीं है

sed 's|literal_pattern|replacement_string|g'

इसलिए, यदि /आपकी समस्या है, तो उपयोग करें |और आपको पूर्व से बचने की आवश्यकता नहीं है।

पीएस: टिप्पणियों के बारे में, यह भी देखें स्टैकओवरफ़्लो का उत्तर पलायन खोज पैटर्न के लिए एक स्ट्रिंग एस्केप पर देखें ।


अद्यतन: यदि आप पर्ल का उपयोग करके ठीक हैं, तो इसके साथ \Qऔर \Eइस तरह की कोशिश करें,
perl -pe 's|\Qliteral_pattern\E|replacement_string|g'
RedGrittyBrickयहां भी एक टिप्पणी में मजबूत पर्ल सिंटैक्स के साथ एक समान चाल का सुझाव दिया गया है


धन्यवाद, मुझे / और के अंतर के बारे में नहीं पता था
एंड्रिया

64
मुझे यकीन है कि यह उत्तर उपयोगी है नहीं कर रहा हूँ ... के बीच फर्क सिर्फ इतना है s|||और s///कि विभाजक चरित्र अलग और इतना है कि है एक चरित्र से बचने की जरूरत नहीं है। आप समान रूप से कर सकते थे s###। यहाँ असली मुद्दा यह है कि ओपी literal_pattern(जो कि शाब्दिक नहीं है और एक रेगेक्स के रूप में व्याख्या की जाएगी) की सामग्री से बचने के बारे में चिंता नहीं करना चाहता है ।
बेंज

15
यह अन्य विशेष वर्णों की व्याख्या से बच नहीं पाएगा। क्या होगा अगर 1234.*aaaआपके समाधान के साथ खोज यह इरादा से बहुत अधिक मेल खाती है 1234\.\*aaa
मैटियो

20
इस उत्तर को स्वीकार नहीं किया जाना चाहिए
स्टीवन लू

2
यह बात पूरी तरह से याद आती है। मिलान किए जाने वाले पाठ में कोई भी स्पष्टता हो सकती है। मेरे मामले में यह एक यादृच्छिक पासवर्ड है। आप जानते हैं कि वे कैसे जाते हैं
क्रिश्चियन बोंगिएरो

13
export FIND='find this'
export REPLACE='replace with this'
ruby -p -i -e "gsub(ENV['FIND'], ENV['REPLACE'])" path/to/file

यह यहाँ केवल 100% सुरक्षित समाधान है, क्योंकि:

  • यह एक स्थैतिक सबस्टेशन है, एक रेग्जेप नहीं, कुछ भी बचने की आवश्यकता नहीं है (इस प्रकार, उपयोग करने के लिए बेहतर sed)
  • यह नहीं टूटेगा अगर आपके तार में }चार (जैसे, प्रस्तुत पर्ल समाधान से बेहतर)
  • यह किसी भी चरित्र के साथ नहीं टूटेगा, क्योंकि ENV['FIND']इसका उपयोग किया जाता है, नहीं $FIND। साथ $FINDया अपने पाठ रूबी कोड में inlined, आप एक सिंटैक्स त्रुटि मारा अगर आपके स्ट्रिंग को कोई अनपेक्षित निहित सकता है '

मुझे export FIND='find this; export REPLACE='replace with this';अपनी बैश स्क्रिप्ट में उपयोग करना था ताकि उसके ENV['FIND']और ENV['replace']अपेक्षित मूल्य हों। मैं एक फ़ाइल में कुछ वास्तव में लंबे एन्क्रिप्टेड तारों की जगह ले रहा था। यह सिर्फ टिकट था।
DMfll

यह एक अच्छा उत्तर है क्योंकि यह विश्वसनीय और माणिक सर्वव्यापी है। इस उत्तर के आधार पर अब मैं इस शेल स्क्रिप्ट का उपयोग करता हूं ।
लोएवॉर्ग

दुर्भाग्य से जब FIND में कई लाइनें नहीं हैं, तो यह काम नहीं करता है।
एड्रेलनोस

ऐसा कुछ भी नहीं है जो इसे FIND में कई लाइनों के साथ काम करने से रोके। डबल उद्धृत \ n का उपयोग करें।
नाऊकेर

7

replaceआदेश यह कर देगा।

https://linux.die.net/man/1/replace

जगह में परिवर्तन:

replace text replacement -- path/to/the/file

टालने के लिए:

replace text replacement < path/to/the/file

उदाहरण:

$ replace '.*' '[^a-z ]{1,3}' <<EOF
> r1: /.*/g
> r2: /.*/gi
> EOF
r1: /[^a-z ]{1,3}/g
r2: /[^a-z ]{1,3}/gi

replaceआदेश MySQL या MariaDB साथ आता है।


3
ध्यान में रखना tht प्रतिस्थापित किया गया है और भविष्य में विवादास्पद नहीं हो सकता
Rogelio

1
पृथ्वी पर ऐसा मूल आदेश डेटाबेस के साथ क्यों आता है?
मास्टरएक्सिलो

3
@masterxilo एक बेहतर सवाल हो सकता है - आधुनिक ऑपरेटिंग सिस्टम के साथ ऐसा मूल कमांड क्यों नहीं आता है? ;-)
मार्क थॉमसन


3

मेरी पर्ल स्क्रिप्ट देखें। नियमित अभिव्यक्ति के निहितार्थ या स्पष्ट उपयोग के बिना आपको ठीक वही करना चाहिए जो:

https://github.com/Samer-Al-iraqi/Linux-str_replace

str_replace Search Replace File # replace in File in place

STDIN | str_replace Search Replace # to STDOUT

बहुत सही है? मुझे इसे करने के लिए पर्ल सीखना था। क्योंकि मुझे वास्तव में इसकी आवश्यकता है।


2

आप इसे अपने पैटर्न से बचकर कर सकते हैं । ऐशे ही:

keyword_raw='1/2/3'
keyword_regexp="$(printf '%s' "$keyword_raw" | sed -e 's/[]\/$*.^|[]/\\&/g')"
# keyword_regexp is now '1\/2\/3'

replacement_raw='2/3/4'
replacement_regexp="$(printf '%s' "$replacement_raw" | sed -e 's/[\/&]/\\&/g')"
# replacement_regexp is now '2\/3\/4'

echo 'a/b/c/1/2/3/d/e/f' | sed -e "s/$keyword_regexp/$replacement_regexp/"
# the last command will print 'a/b/c/2/3/4/d/e/f'

इस समाधान के लिए क्रेडिट यहां जाता है: https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern

नोट 1: यह केवल गैर-रिक्त कीवर्ड के लिए काम करता है। खाली कीवर्ड sed ( sed -e 's//replacement/') द्वारा स्वीकार नहीं किए जाते हैं ।

नोट 2: दुर्भाग्य से, मैं एक लोकप्रिय उपकरण नहीं जानता, जो समस्या को हल करने के लिए regexp-s का उपयोग नहीं करेगा। आप Rust या C में ऐसा टूल लिख सकते हैं, लेकिन यह डिफ़ॉल्ट रूप से नहीं है।


यह ओपी की बात को पूरी तरह याद करता है। जाहिर है आप पैटर्न से बच सकते हैं, लेकिन कुछ पैटर्न के लिए यह थकाऊ है।
icecreamword

@icecreamword क्या आपने पहली पंक्ति के नीचे मेरा उत्तर पढ़ा है? स्क्रिप्ट से बचने करता है स्वचालित रूप से
वास्यानोविकोव

1

मैंने कुछ अन्य उत्तर एक साथ दिए और इसके साथ आया:

function unregex {
   # This is a function because dealing with quotes is a pain.
   # http://stackoverflow.com/a/2705678/120999
   sed -e 's/[]\/()$*.^|[]/\\&/g' <<< "$1"
}
function fsed {
   local find=$(unregex "$1")
   local replace=$(unregex "$2")
   shift 2
   # sed -i is only supported in GNU sed.
   #sed -i "s/$find/$replace/g" "$@"
   perl -p -i -e "s/$find/$replace/g" "$@"
}

Newlines के साथ काम नहीं करता है। इसके साथ ही नई सुर्खियों से भागने में मदद नहीं करता है \n। कोई भी समाधान?
एड्रेलनोस

1

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

php -R 'echo str_replace("\|!£$%&/()=?^\"'\''","replace",$argn),PHP_EOL;'<input.txt >output.txt

नोट: आपको फिर भी सिंगल कोट्स 'और डबल कोट्स से बचना होगा "


0

Node.JS @Nowaker के समकक्ष:

export FNAME='moo.txt'
export FIND='search'
export REPLACE='rpl'
node -e 'fs=require("fs");fs.readFile(process.env.FNAME,"utf8",(err,data)=>{if(err!=null)throw err;fs.writeFile(process.env.FNAME,data.replace(process.env.FIND,process.env.REPLACE),"utf8",e=>{if(e!=null)throw e;});});'

0

एक और "लगभग" काम करने का तरीका।

Vi या vim का प्रयोग करें।

इसमें अपने प्रतिस्थापन के साथ एक textfile बनाएँ:

:% sno / my search string \\ "-: # 2; g ('। j'); \\"> / my replacestring = \\ "bac) (o: # 46; \\"> /
:एक्स

उसके बाद कमांड से vi या vim निष्पादित करें:

vi -S commandfile.txt path/to/the/file

:% स्नो जादू के बिना खोज करने और बदलने के लिए vi कमांड है।

/ मेरा चुना हुआ विभाजक है।

: x बचाता है और vi से बाहर निकलता है।

आपको बैकस्लैश से बचने की जरूरत है '' फॉरवर्डलैश '/' को उदाहरणार्थ एक प्रश्नवाचक चिह्न के साथ बदला जा सकता है? ' या कुछ और जो आपकी खोज या प्रतिस्थापन-स्ट्रिंग, पाइप में नहीं है '|' मेरे लिए काम नहीं किया

रेफरी: https://stackoverflow.com/questions/6254820/perform-a-non-regex-search-replace-in-vim https://vim.fandom.com/wiki/Search_without_nith_to_escape_slash http://linuxcommand.org/ lc3_man_pages / vim1.html

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