बाइनरी के बजाय ज़ार का उपयोग करें


14

सेंटोस 6.5 पर बैश 4.2:

मेरे ~/.bash_profileपास में उपनामों का एक समूह है, जिसमें शामिल हैं:

alias grep='grep -n --color=always'

ताकि मैं रंग हाइलाइटिंग और प्रिंट लाइन नंबर स्वचालित रूप से चलाते समय प्राप्त कर सकूं grep। यदि मैं निम्नलिखित कार्य करता हूं, तो उम्मीद के मुताबिक काम करता है:

$ grep -Re 'regex_here' *.py

हालाँकि, जब मैंने इसे हाल ही में चलाया:

$ find . -name '*.py' | xargs grep -E 'regex_here'

परिणाम हाइलाइट नहीं किए गए थे और लाइन नंबर मुद्रित नहीं किए गए थे, जिससे मुझे वापस जाने और स्पष्ट रूप -n --color=alwaysसे grepकमांड में जोड़ने के लिए मजबूर होना पड़ा ।

  • क्या xargsवातावरण में उपनाम नहीं पढ़ा जाता है?
  • यदि नहीं, तो क्या ऐसा करने का कोई तरीका है?

यह प्रश्नोत्तर आपको चाहिए।
Psimon

@psimon सही, यह अनिवार्य रूप से वही करने के लिए कह रहा है जो मैंने पहले ही अपने वर्कअराउंड में किया था - मुझे अपने उपनाम को xargsकमांड में मैन्युअल रूप से विस्तारित करना था। क्या मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या कोई ऐसा तरीका है जिससे मैं सीधे अपने उपनाम को कॉल कर सकता हूं xargs
मैटडामो

1
क्या आपने export GREP_OPTIONS='-n --color=always'अपने xargs कमांड से पहले कोशिश की है ?
doneal24

@ डौगो 'धन्यवाद, कि काम किया! मैं उसे अपने साथ जोड़ूंगा .bash_profile। एक उत्तर लिखने के लिए स्वतंत्र महसूस करें ...
मट्टडामो

जवाबों:


11

एक उपनाम शेल में आंतरिक होता है जहां इसे परिभाषित किया जाता है। यह अन्य प्रक्रियाओं के लिए दृश्यमान नहीं है। वही शेल फंक्शंस के लिए जाता है। xargsएक अलग अनुप्रयोग है, जो एक शेल नहीं है, इसलिए इसमें उपनाम या फ़ंक्शन की अवधारणा नहीं है।

आप xargs को grepसीधे इन्वॉल्व करने के बजाय शेल खोल सकते हैं । हालाँकि, केवल शेल खोलना ही पर्याप्त नहीं है, आपको उस शेल में भी अन्य को परिभाषित करना होगा। यदि उपनाम आपके में परिभाषित किया गया है .bashrc, तो आप उस फ़ाइल को स्रोत कर सकते हैं; हालाँकि यह आपके .bashrcअन्य कार्यों को काम नहीं कर सकता है जो एक गैर-इंटरैक्टिव शेल में कोई मतलब नहीं रखते हैं।

find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _

Regexp टाइप करते समय नेस्टेड उद्धरण की जटिलताओं से सावधान रहें। आप शेल के एक पैरामीटर के रूप में regexp पास करके अपने जीवन को सरल बना सकते हैं।

find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here

आप स्पष्ट रूप से उपनाम खोज कर सकते हैं। फिर xargsदेखेंगे grep -n --color=always

find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here

Zsh में:

find . -name '*.py' | xargs $aliases[grep] regex_here

वैसे, ध्यान दें कि find … | xargs … रिक्त स्थान (दूसरों के बीच) वाले फ़ाइलनाम पर टूट जाता है । आप इसे नल-सीमांकित रिकॉर्ड में बदलकर ठीक कर सकते हैं:

find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here

या उपयोग करके -exec:

find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +

कॉल करने के बजाय find, आप पूरी तरह से शेल के अंदर सब कुछ कर सकते हैं। ग्लोब पैटर्न **/ट्रैवर्सेस निर्देशिकाओं को पुनरावर्ती बनाता है। बैश में, आपको shopt -s globstarपहले इस ग्लोब पैटर्न को सक्षम करने के लिए दौड़ना होगा।

grep regex_here **/*.py

इसकी कुछ सीमाएँ हैं:

  • यदि बहुत सारी फाइलें मेल खाती हैं (या यदि उनके पास लंबे रास्ते हैं), तो कमांड विफल हो सकती है क्योंकि यह अधिकतम कमांड लाइन की लंबाई से अधिक है।
  • Bash b4.2 में (लेकिन अधिक हाल के संस्करणों में नहीं, न ही ksh या zsh में), **/निर्देशिकाओं के प्रतीकात्मक लिंक में पुनरावृत्ति करता है।

एक अन्य दृष्टिकोण प्रक्रिया प्रतिस्थापन का उपयोग करना है, जैसा कि मारियसमैटुटिया द्वारा सुझाया गया है

grep regex_here <(find . -name '*.py')

यह तब **/लागू होता है जब यह लागू नहीं होता है: जटिल findअभिव्यक्तियों के लिए, या जब आप सांकेतिक लिंक के तहत पुनरावृत्ति नहीं करना चाहते हैं, तो ≤4.2 को रोकें। ध्यान दें कि यह रिक्त स्थान वाले फ़ाइल नामों पर टूटता है; ग्लोबिंग को सेट IFSऔर अक्षम करने के लिए एक वर्कअराउंड है , लेकिन यह थोड़ा जटिल होने लगा है:

(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )

उपनामों की अन्य प्रक्रियाओं के लिए दृश्यमान क्यों नहीं हैं, इसके स्पष्ट स्पष्टीकरण के लिए धन्यवाद
मैटडामो

एक प्रक्रिया प्रतिस्थापन का उपयोग भी कर सकता है, मेरा उत्तर देखें।
MariusMatutiae

11

उपयोग alias xargs='xargs '

alias: alias [-p] [name[=value] ... ]
(snip)
A trailing space in VALUE causes the next word to be checked for
alias substitution when the alias is expanded.

उस के लिए धन्यवाद, मैं अनुगामी अंतरिक्ष चाल के बारे में पता नहीं था।
1

Np। यह भी उपयोगी है sudo
1.61803

2

कृपया इसे दूसरे दृष्टिकोण के प्रदर्शन के रूप में लें, जिसे मैं संबंधित SO प्रश्न में नहीं पा सकता हूं :

आप एक रैपर फ़ंक्शन लिख सकते हैं xargsजिसके लिए यह जांचता है कि क्या पहला तर्क एक उपनाम है और यदि हां, तो उसके अनुसार विस्तार करें।

यहाँ एक कोड है जो कि वास्तव में करता है लेकिन दुर्भाग्य से यह आवश्यकता है जेड खोल और इसलिए 1 नहीं चलता है: बैश के साथ 1 (और स्पष्ट रूप से, मैं करने के लिए इस्तेमाल नहीं कर रहा हूँ बैश यह बंदरगाह करने के लिए पर्याप्त):

xargs () {
        local expandalias
        if [[ $(which $1) =~ "alias" ]]; then
                expandalias=$(builtin alias $1) 
                expandalias="${${(s.'.)expandalias}[2]}"
        else
                expandalias=$1
        fi
        command xargs ${(z)expandalias} "${(z)@[2,-1]}"
}

प्रमाण, कि यह काम करता है:

zsh% उर्फ grep = "grep -n"                           line # में मैच की लाइन संख्या शामिल है
zsh% foo -name "* .p *" खोजें | xargs grep -E परीक्षण
foo / bar.p0: 151: # डेटा = परीक्षण
foo / bar.p1: 122: # डेटा = टेस्ट # लाइन नंबर शामिल
zsh% unalias grep 
zsh% foo -name "* .p *" खोजें | xargs grep -E परीक्षण
foo / bar.p0: # डेटा = परीक्षण
foo / bar.p1: # डेटा = परीक्षण # पंक्ति संख्याएं शामिल नहीं हैं
zsh% 

1

एक सरल, और अधिक सुरुचिपूर्ण समाधान, प्रक्रिया प्रतिस्थापन का उपयोग करना है :

grep -E 'regex_here' <( find . -name '*.py')

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

बस पुनर्निर्देशन और कोष्ठक के बीच कोई जगह नहीं छोड़ने के लिए सावधान रहें, अन्यथा बैश एक त्रुटि फेंक देंगे। मेरे ज्ञान का सबसे अच्छा करने के लिए, प्रक्रिया प्रतिस्थापन बाश, ज़श, क्ष {88,93} द्वारा समर्थित है, लेकिन pdksh द्वारा नहीं (मुझे बताया गया है कि अभी तक नहीं होना चाहिए )।


मुझे लगता है कि pdksh विकास मर चुका है। Mksh कमोबेश एक उत्तराधिकारी प्रोजेक्ट है - "बहुत कठिन, यह पता चला है (पार्सिंग कॉन्सेप्ट tg @ s हेड में किया गया है")
गिल्स एसओ- बुराई को रोकना '

प्रक्रिया प्रतिस्थापन जटिल findआज्ञाओं के लिए एक अच्छी विधि है , हालांकि आपको सावधान रहना होगा कि यह रिक्त स्थान पर टूट जाएगा, और जिसे आसानी से तय नहीं किया find | xargsजा सकता है (स्विच करने -print0और -0, या उपयोग करके -exec)। जब लागू होता है, **/तो सरल और अधिक मजबूत होता है।
गिल्स एसओ- बुराई को रोकना '

0

grep पर्यावरण चर GREP_OPTIONS से ​​डिफ़ॉल्ट विकल्पों का एक सेट पढ़ेगा। डालोगे तो

 export GREP_OPTIONS='--line-number --color=always'

आपके .bashrc में तब चर को सबस्क्राइब करने के लिए पास किया जाएगा और आपको अपेक्षित परिणाम मिलेंगे।


लेकिन न डालें --line-numberया --color=alwaysमें GREP_OPTIONSजब तक यह सिर्फ एक आदेश के लिए है, इस स्क्रिप्ट का एक बहुत टूट जाएगा। --color=autoवहाँ है ठीक है, और यह सब के बारे में है। इस लाइन को अपने में रखने .bashrcसे बहुत सारा सामान टूट जाएगा।
गिल्स एसओ- बुराई को रोकना '

@ गिल्स किसी भी अलायन्स को सेट करना या रूट अकाउंट के लिए किसी भी कमांड के लिए डिफॉल्ट विकल्प को ओवरराइड करना एक बुरी बात है। उपयोगकर्ता खाते के लिए इन विकल्पों को सेट करना कई समस्याओं का कारण नहीं है। मैं किसी भी उपयोगकर्ता स्क्रिप्ट के साथ नहीं आ सकता है जो समस्याग्रस्त हैं।
doneal24

बस किसी भी स्क्रिप्ट के बारे में जो एक तरह से grep का उपयोग करता है जो एक घटना की उपस्थिति का परीक्षण करने से परे जाता है। उदाहरण के लिए, /etc/init.d/cronमेरे सिस्टम से value=`egrep "^${var}=" "$ENV_FILE" | tail -n1 | cut -d= -f2` :। या फिर से /usr/bin/pdfjam: pdftitl=`printf "%s" "$PDFinfo" | grep -e … | sed -e …` । स्क्रिप्ट में दिखाई नहीं देने के कारण एक उपनाम अन्य समस्या नहीं है।
गिल्स एसओ- बुराई को रोकना '

@ गिल्स मैं इस तरह की कई स्क्रिप्ट्स से वाकिफ हूं। जिन्हें मैं प्राप्त नहीं कर सकता, वे आम तौर पर केवल रूट (जैसे /etc/init.d/cron) द्वारा चलाए जाते हैं। व्यक्तिगत रूप से, मेरे पास मेरे उपयोगकर्ता खातों पर कोई भी उपनाम परिभाषित नहीं है और न ही मैं कमांडों के डिफ़ॉल्ट व्यवहार को ओवरराइड करने के लिए एक आरसी फ़ाइल या पर्यावरण चर के माध्यम से विकल्प निर्धारित करता हूं। मैं सुविधा के बारे में भविष्यवाणी करना पसंद करता हूं।
doneal24

स्क्रिप्ट्स द्वारा देखे जाने के बाद से उपनामों की भविष्यवाणी नहीं टूटती है। GREP_OPTIONSकुछ विकल्पों को छोड़कर --color=auto( जैसे यह किसके लिए डिज़ाइन किया गया था) को छोड़कर, बहुत ही बुरी तरह से भविष्यवाणी की स्थापना बहुत खराब है ।
गिल्स एसओ- बुराई को रोकना '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.