क्या मैं 'tr' जैसे अक्षरों का अनुवाद करने के लिए `sed 'का उपयोग कर सकता हूँ?


14

मैं इसी तरह के पात्रों के एक सेट को दूसरे सेट से बदलना चाहता हूं, कुछ इस तरह से:

original set: ots
"target" set: u.x

foobartest → fuubar.ex.

इस तरह अनुवाद / अनुवाद करना trकमांड की विशेषता है :

$ echo 'foobartest' | tr 'ots' 'u.x'
fuubar.ex.

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


इस सवाल का स्व-उत्तर देने के बाद से मैं "sed ट्रांसलेट कैरेक्टर्स" के लिए कोई परिणाम नहीं ढूंढ सका। मैजिक कीवर्ड "ट्रांसपेरेट" होने के कारण समाप्त हो गया, लेकिन मुझे लगा कि यह इस फीचर को आसानी से खोजने योग्य है।
n.st

इसके लिए वर्कअराउंड को लागू करने का प्रयास करते समय कुछ ध्यान में रखें: tr(सही ढंग से) प्रतिस्थापन सेट में पुनरावृत्ति को अनदेखा करता है: echo 'abc' | tr ab bxbxc। एक आदिम समाधान कसाई हो सकता है xxcक्योंकि यह उन अनुवादों को फिर से लागू करता है जिन्हें पहले ही अनुवादित किया जा चुका है।
n.st

संबंधित: यूनिकोड वर्णों के लिए ट्र एनालॉग? (जीएनयू के sedविपरीत जीएनयू trमल्टी-बाइट पात्रों को लिप्यंतरित कर सकता है)
स्टीफन चेज़लस

यदि आप एक और संभावना चाहते हैं: पर्ल अनुवाद कर सकता है, और -i, और (जब तक कि प्राचीन) मल्टीबीट नहीं। POSIX नहीं, लेकिन बहुत आम है।
dave_thompson_085

जवाबों:


24

sedहै yआदेश है कि बस की तरह काम करता tr:

$ echo 'foobartest' | sed 'y/ots/u.x/'
fuubar.ex.

yआदेश हिस्सा है POSIX sedविनिर्देश , तो यह पर काम करना चाहिए बस किसी भी मंच के बारे में।

और चूंकि यह है sed, आप इसे अपने संपादित संस्करण के साथ एक फ़ाइल को बदल सकते हैं, आपको परेशान करने वाले अस्थायी फ़ाइल व्यवसाय को प्रदान करते हैं (बशर्ते आपके sedसमर्थन का -iविकल्प लागू होता है, जो POSIX द्वारा निर्दिष्ट नहीं है):

$ sed -i 'y/ots/u.x/' some-file.txt

@ स्टीफनचेलजेलस ने इस ओर इशारा करने के लिए धन्यवाद; मुझे अब तक के आंतरिक कामकाज की जानकारी नहीं थी। मैंने अपना उत्तर उस उल्लेख के लिए संपादित किया है।
n.st

धन्यवाद, यह असाधारण रूप से उपयोगी है! मैं यह उम्मीद कर रहा था कि यह वीआईएम (सेंटोस 7.3 पर 8.0.1092) में काम करेगा, लेकिन ऐसा नहीं है। कुछ भी नहीं करना चाहिए sed, VIM करते हैं?
डिटानचेन

1
@dotancohen सिर्फ इसलिए कि विम के प्रतिस्थापन समारोह के बाद sedअन्य कार्यों के रूप में अच्छी तरह से मतलब नहीं है मॉडलिंग की है । ;) विम मेलिंग सूची में एक समान खोजने के बारे में एक धागा हैy/abc/def/ ; सबसे अच्छा विकल्प लगता है :%call setline(".", tr(getline("."),"abc","def"))
n.st

8

यदि आपके मामले में, आप अपने आकार को बदलने के बिना वर्णों का अनुवाद कर रहे हैं (वैसे भी, कुछ कार्यान्वयन जैसे GNU trकेवल एकल-बाइट वर्णों का समर्थन करते हैं), आप कर सकते हैं:

tr 'ots' 'u.x' < file 1<> file

अर्थात्, trफ़ाइल को अपने आप से अधिलेखित करें।

यह sed -iकई खातों से बेहतर है :

  • इसके लिए अतिरिक्त डिस्क स्थान की आवश्यकता नहीं है (कुछ विरल फ़ाइल को छोड़कर, कॉपी-ऑन-राइट स्पेशल केस)
  • यह इनकोड संख्या, स्वामित्व, अनुमतियाँ, ACLs को सुरक्षित रखता है ...
  • यह सिमिलिंक के साथ ठीक काम करता है, यह हार्ड लिंक को नहीं तोड़ता है
  • यह अस्थायी फ़ाइलों को तब नहीं छोड़ता है जब मारे जाते हैं।

एक दोष यह है कि यदि यह बाधित हो जाता है, तो फ़ाइल आधा-अनुवादित हो जाएगी (इस मामले में, हालांकि, आप इसे समाप्त करने के लिए इसे फिर से चला सकते हैं)। कुछ sedकार्यान्वयन संभाल लेंगे कि सही ढंग से सुनिश्चित करें कि मूल फ़ाइल अपरिवर्तित रहती है जब तक कि कमांड सफल न हो।


3
यदि आपने अनुवाद सेट में पुनरावृत्ति प्राप्त की है, तो अनुवाद को फिर से चलाएं echo 'abc' | tr ab bx
n.st

1
@ n.st, हां, इसीलिए मैंने इस मामले में कहा , हालांकि मैं मानता हूं कि यह इसे वर्तनी के लायक है।
स्टीफन चेज़लस

अंत में, मुझे सभी के बाद अस्थायी फ़ाइलों के साथ काम करना पड़ा: gist.github.com/n-st/048facd0c12f105ac12203030bbbb962f - मल्टीबाइट वर्णों ने GNU का उपयोग करना असंभव बना दिया trऔर हमारे सहानुभूति-भारी PXE वातावरण में, sed -iएक स्क्रू-अप प्रतीक्षा थी होने के लिए…: /
n.st

@ n.st, उसके iconv -t cp437लिए अधिक उपयुक्त लगता है।
स्टीफन चेज़लस

iconvटूट जाता है जब इनपुट फ़ाइल में पहले से ही cp437- एन्कोडेड बाइट्स या कई एनकोडिंग का मिश्रण होता है। इसलिए जब यह सामान्य मामले में बेहतर होता है, तो इस मामले में मैन्युअल प्रतिस्थापन करना अधिक मजबूत होता है।
n.st

4

एक अन्य विकल्प के रूप में, यदि आपका मुख्य मुद्दा फाइलों को इन-प्लेस बदलने के लिए समर्थन की कमी है, तो आपको टूलटाइल पैकेजsponge से उपकरण में रुचि हो सकती है :

tr 'ots' 'u.x' < file | sponge file

लिखेंगे file, लेकिन fileइनपुट पूरा होने के बाद ही लिखने के लिए खोलें । से मैनपेज :

spongeमानक इनपुट पढ़ता है और इसे निर्दिष्ट फ़ाइल पर लिखता है। शेल पुनर्निर्देशित के विपरीत, स्पंज आउटपुट फ़ाइल खोलने से पहले अपने सभी इनपुट को भिगो देता है। यह उन पाइपलाइनों का निर्माण करने की अनुमति देता है जो उसी फ़ाइल से पढ़ते हैं और लिखते हैं।

जब तक आपके पास वास्तव में बड़ी फाइलें हैं जो स्मृति में आयोजित नहीं की जा spongeसकती हैं, आपके लिए काम कर सकती हैं।


2
इसके साथ एक मुद्दा spongeयह है कि यह अभी भी अधिलेखित है fileअगर trविफल रहता है (उदाहरण के लिए यदि आपने लिखा था, लेकिन पढ़ने के लिए उपयोग नहीं किया गया था file)
स्टीफन चेज़लस

ओह, वास्तव में यह करता है; मुझे उम्मीद नहीं थी कि धन्यवाद।
माइंडट्री

cat file >; fileKsh93 के ऑपरेटर को देखें जो आउटपुट को एक तिपहिया पर लिखता है जिसे केवल तब ही नाम बदल दिया जाता है जब कमांड सफल होता है (लेकिन पसंद है sed -i, जो मूल को अधिलेखित करने के बजाय एक नई फ़ाइल बनाता है)।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.