क्या एक पाइपलाइन में कई tr प्रक्रियाओं से बचने के लिए tr कमांड्स को जंजीर बनाया जा सकता है?


11

मेरे पास txt फ़ाइलों का एक गुच्छा है, मैं उन्हें लो-केसेड, केवल अल्फाबेटिक और एक शब्द-प्रति पंक्ति आउटपुट करना चाहता हूं, मैं इसे trइस तरह से एक पाइपलाइन में कई कमांड के साथ कर सकता हूं :

tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'

क्या एक स्कैन में ऐसा करना संभव है? मैं एक सी प्रोग्राम यह करने के लिए लिख सकता है, लेकिन मुझे लगता है कि वहाँ का उपयोग कर यह करने के लिए एक तरह से है जैसे tr, sed, awkया perl


आप कौन सा ओएस उपयोग कर रहे हैं? क्या आपके पास GNU टूल्स तक पहुँच है?
terdon

जवाबों:


9

आप कई अनुवादों को जोड़ सकते हैं (जटिल मामलों में ओवरलैपिंग-लोकेल-डिपेंडेंट सेटों को छोड़कर), लेकिन आप अनुवाद के साथ विलोपन को संयोजित नहीं कर सकते।

<doyle_sherlock_holmes.txt tr -d '[:punct:]' | tr '[:upper:] ' '[:lower:]\n'

दो कॉल के लिए trएक कॉल की तुलना में अधिक जटिल उपकरणों के तेजी से होने की संभावना है, लेकिन यह इनपुट आकार पर बहुत भिन्न है, विभिन्न वर्णों के अनुपात trपर, ऑपरेटिंग सिस्टम पर और प्रतिस्पर्धा उपकरणों के कार्यान्वयन पर, संख्या पर कोर का, आदि।


मुझे यकीन नहीं है कि संयोजनtr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
कोस्टास

1
@ कॉस्टस विराम चिह्नों को न्यूलाइन्स में बदल देगा। यह इस विशेष अनुप्रयोग के लिए ठीक हो सकता है, लेकिन आउटपुट मूल के समान नहीं है।
गिल्स एसओ- बुराई को रोकें '

@ कोस्टस - जबकि न्यूलाइन चीज़ यहाँ पर एकान्त हो सकती है, मुझे नहीं लगता कि अपरकेस चार्ट को निचोड़ना होगा। उदाहरण के लिए: printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'हो जाता है a\na\na', और परिवर्तन के लिए ... '[:lower:]\n'जरूरी कुछ भी करने के लिए बिल्कुल भी कुछ भी नहीं कर सकता '[:punct:]'है - कुछ trएस 2 से मैच करने के लिए सेट 1 को छोटा करेगा और कुछ एक निहित होगा [\n*]। यह बेहतर है कि आप वहां सीमा का उपयोग करें।
mikeserv

4

यहाँ कुछ दृष्टिकोण हैं:

  • जीएनयू grepऔर tr: सभी शब्दों को ढूंढते हैं और उन्हें निचला मामला बनाते हैं

    grep -Po '\w+' file | tr '[A-Z]' '[a-z]'
  • GNU ग्रिप और पर्ल: जैसा कि ऊपर है, लेकिन पर्ल लोअर केस में रूपांतरण को संभालता है

    grep -Po '\w+' file | perl -lne 'print lc()'
  • perl: सभी वर्णमाला वर्णों को ढूंढें और उन्हें निचले मामले में प्रिंट करें (धन्यवाद @steeldriver):

    perl -lne 'print lc for /[a-z]+/ig' file
  • sed: सभी वर्णों को हटाएं जो वर्णमाला या रिक्त स्थान नहीं हैं, सभी वर्णमाला वर्णों को उनके निचले केस संस्करणों के साथ स्थानापन्न करें और सभी स्थानों को नई वर्णमाला के साथ बदलें। ध्यान दें कि यह मानता है कि सभी व्हाट्सएप रिक्त स्थान हैं, कोई टैब नहीं।

    sed 's/[^a-zA-Z ]\+//g;s/[a-zA-Z]\+/\L&/g; s/ \+/\n/g' file

2
क्या कुछ perl -lne 'print lc for /[[:alpha:]]+/g'काम भी आएगा? या यह गरीब शैली है? (मैं
हैरान

@steeldriver हाँ, यह अच्छा होगा! यदि आप पर्ल सीख रहे हैं, तो मुझे यकीन है कि आप इसके आदर्श वाक्य पर आए हैं: TMTOWTDI :) धन्यवाद, मैं इसे जोड़ूंगा
terdon

3
नए संस्करण के साथ (> ४.२.१)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
कोस्टास

@ कोस्टास आह, अब sedकर सकते \wहैं? ठंडा!
terdon

@terdon - यह किया गया है कि थोड़ी देर के लिए, लेकिन, क्योंकि कोस्टास ने इसका उल्लेख नहीं किया था, मुझे लगता है कि उपरोक्त टिप्पणी के बारे में सबसे दिलचस्प बात यह है कि GNU sedका -zero delimit स्विच है - यह \0NULnewlines के बजाय s से अधिक चक्र है। बहुत अच्छा है जब आप कुछ ऐसा करते हैं tar -c . | tr -s \\0 | sed -z ...- लेकिन थोड़े धीमे।
mikeserv

4

हाँ। आप उस w / trको ASCII लोकेल में कर सकते हैं (जो कि, GNU के लिए tr, वैसे भी, केवल इसका एक प्रकार है) । आप POSIX कक्षाओं का उपयोग कर सकते हैं, या आप प्रत्येक वर्ण के बाइट मानों को अष्टक संख्या द्वारा संदर्भित कर सकते हैं। आप उनके परिवर्तनों को श्रेणियों में विभाजित कर सकते हैं, साथ ही साथ।

LC_ALL=C tr '[:upper:]\0-\101\133-140\173-\377' '[:lower:][\n*]' <input

उपरोक्त आदेश सभी अपरकेस वर्णों को लोअरकेस में बदल देगा, लोअरकेस वर्णों को पूरी तरह से अनदेखा कर देगा, और अन्य सभी वर्णों को नई सुर्खियों में बदल देगा। बेशक, फिर आप एक टन खाली लाइनों के साथ हवा करते हैं। tr -sQueeze दोहराता स्विच उस मामले में उपयोगी हो सकता है, लेकिन अगर आप के साथ इसका इस्तेमाल [:upper:]करने के लिए [:lower:]तो परिवर्तन आप अच्छी तरह से अपरकेस वर्णों फैलाएंगे हवा। इस तरह यह अभी भी एक दूसरे फिल्टर की तरह की आवश्यकता है ...

LC... tr ... | tr -s \\n

... या ...

LC... tr ... | grep .

... और इसलिए यह हवाओं को करने की तुलना में बहुत कम सुविधाजनक है ...

LC_ALL=C tr -sc '[:alpha:]' \\n <input | tr '[:upper:]' '[:lower:]'

... जो -cएक ही नई पंक्ति में अनुक्रम द्वारा वर्णमाला वर्णों के बहिष्कार को निचोड़ता है, फिर पाइप के दूसरी तरफ ऊपरी से निचले परिवर्तन करता है।

यह कहना नहीं है कि उस प्रकृति की श्रेणियाँ उपयोगी नहीं हैं। सामान की तरह:

tr '\0-\377' '[1*25][2*25][3*25][4*25][5*25][6*25][7*25][8*25][9*25][0*]' </dev/random

... यह बहुत उपयोगी हो सकता है क्योंकि यह इनपुट बाइट्स को उनके मूल्यों के प्रसार स्पेक्ट्रम पर सभी अंकों में परिवर्तित करता है। बर्बाद नहीं, नहीं चाहिए, तुम्हें पता है।

परिवर्तन करने के लिए एक और तरीका शामिल हो सकता है dd

tr '\0-\377' '[A*64][B*64][C*64][D*64]' </dev/urandom |
dd bs=32 cbs=8 conv=unblock,lcase count=1

dadbbdbd
ddaaddab
ddbadbaa
bdbdcadd

क्योंकि एक ही समय में ddदोनों unblockऔर lcaseरूपांतरण कर सकते हैं , यह भी संभव है कि इसे बंद करने के लिए बहुत से कार्य पारित किए जाएं। लेकिन यह वास्तव में केवल तभी उपयोगी हो सकता है जब आप प्रति शब्द बाइट्स की संख्या का सटीक अनुमान लगा सकें - या कम से कम एक पूर्वानुमान बाइट की गिनती के लिए पहले से ही रिक्त स्थान के साथ प्रत्येक शब्द को पैड कर सकते हैं, क्योंकि unblockप्रत्येक ब्लॉक के अंत में अनुगामी रिक्त स्थान खाती है।


ddशामिल होने के लिए +2 बोनस अंक :)
tlehman

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