अंतिम कमांड में फॉरवर्ड स्लैश के लिए सब्स्टिट्यूट बैकस्लैश


10

मैंने cd C:\foo\bar\PowerShell से Cygwin को कमांड कॉपी किया है और इसे निष्पादित करने के लिए बहुत उम्मीद है। मैं अब सब के \साथ बदलने के लिए एक प्रतिस्थापन चलाने की कोशिश कर रहा हूँ /:

$ !!:gs/\\/\/
bash: :gs/\\/\/: substitution failed

मुझे यकीन नहीं है कि मुझे प्रतिस्थापन क्यों नहीं मिल रहा है।

मैंने भी कोशिश की:

$ !!:gs/\\/q

बस यह देखने के लिए कि क्या समस्या थी। यह। अब मैं उत्सुक हूँ!

मुझे "प्रतिस्थापन विफल" क्यों हो रहा है?


2
मेरे पास अभी कोई साइबरविन नहीं है, लेकिन मैंने सोचा, कि विंडोज पथ काम कर रहे हैं ... क्या आपने तर्क को गाने की कोशिश की है? यानीcd 'C:\foo\bar'
MPY

@mpy यह वास्तव में भी काम करता है! पता नहीं था कि मैं प्रतिस्थापन के साथ फंस नहीं गया था।
टान्नर फॉकनर

1
"Zsh का उपयोग करते हुए एक उत्तर के लिए खुला होगा"। आपका मूल !!:gs/\\/\/कार्य zsh में काम करता है ...
कामिल

@TannerFaulkner fc -s '\'='/' -1उबंटू LTS डिफ़ॉल्ट बैश के तहत काम करता है। मुझे बताएं कि क्या यह साइगविन के तहत भी काम करता है। मैंने उत्तर में और शब्द पोस्ट किए।
हस्त्तूर

1
मुझे लगता है कि सामान्य बैश व्यवहार यहाँ है कि बैकस्लैश को संसाधित किया जाता है क्योंकि प्रतिस्थापन होने से पहले बच निकलता है !!:gs/\\/\//। @ हस्तूर fc -s '\'='/' -1को अपेक्षित व्यवहार मिलता है। यह बैश में एक बग हो सकता है।
क्विकोटिक

जवाबों:


6

फ़ॉरवर्ड स्लैश आपके स्थानापन्न कमांड का परिसीमन भी है, इसलिए आपको इसे प्रतिस्थापन स्ट्रिंग के रूप में बचाना चाहिए ताकि प्रतिस्थापन जल्दी समाप्त न हो सके

!!:gs/\\/\//

या अधिक स्पष्ट रूप से टिप्पणियों में सुझाए गए अनुसार, सीमांकक के रूप में स्लैश के अलावा कुछ का उपयोग करके

!!:gs|\\|/|

लेकिन यह केवल काम करने के लिए लगता है tcsh(शेल आमतौर पर मुझे सौंपा गया है), मुझे काम करने की आज्ञा नहीं मिल सकती bashक्योंकि ऐसा लगता है कि भागने से पहले तर्क पर काम नहीं होता है:s


कोई खुशी नहीं :( एक ही त्रुटि i.imgur.com/QFQR0xF.png
टान्नर फॉल्कनर

1
बस एक टिप्पणी: !!:gs|\\|/थोड़ा अधिक पठनीय हो सकता है।
मपी

1
मैं इसे बाश में काम करने के लिए नहीं मिला। के पहले आर्ग :sdoen't एक असली regex होने लगते हैं
infixed

4

संक्षिप्त उत्तर: बैश का बिलियन fc(फिक्स कमांड)

fcइतिहास के आदेशों को संपादित करने और फिर से निष्पादित करने के लिए बने बैश शेल में अंतर्निहित कमांड है ।
यह साइगविन पर भी मौजूद है और यह उन सभी लिनक्स वितरणों पर काम करता है जिन पर मैंने परीक्षण किया है:

fc  -s '\'='/' -1

कुछ स्पष्टीकरण

  • fcइतिहास सूची से आदेशों को सूचीबद्ध या संपादित करने और फिर से निष्पादित करने के लिए bash बिल्ट-इन कमांड है।
  • -1इतिहास में अंतिम आदेश ले जाएगा। ध्यान दें कि यहां तक !!कि परिभाषित (से पढ़ें man bash) के रूप में है

    !! Refer to the previous command. This is a synonym for-1! '

  • -sएक पैटर्न को दूसरे के साथ बदलना। इस बार help fc(बिल्ट-इन कमांड से help):

    `Fc -s [pat = rep ...] [कमांड] प्रारूप के साथ, COMMAND को प्रतिस्थापन OLD = NEW के प्रदर्शन के बाद फिर से निष्पादित किया जाता है।

    ठीक है वे pat=repइसके बजाय मतलब है OLD=NEW...

  • पैटर्न शेल द्वारा पढ़ा जाएगा इसलिए हमें उन्हें उद्धरण के साथ संरक्षित करना होगा: '\'और '/'

कुछ शब्द इस बारे में अधिक क्यों आपको "प्रतिस्थापन विफल" हो रहे हैं

ऐसा लगता है कि s संशोधक के लिए (अभी तक) बैकस्लैश चरित्र के प्रतिस्थापन को लागू नहीं किया गया है \, जो कि पलायन एक है। यह सुनिश्चित करने के लिए हमें कोड को देखना चाहिए, उदाहरण के लिए, बैश इतिहास विस्तार के गन्नू संस्करण का (लेकिन उपरोक्त कमांड प्राप्त करने के लिए कि आप क्या करने की कोशिश कर रहे थे ... तो मैं इसे आलसी लेता हूं ....)।

कुछ नोट:

  1. हम यह सोचकर आगे बढ़ रहे हैं कि यह प्रत्येक RegEx के साथ काम करेगा जिसे हम काम कर रहे हैं sed, लेकिन इसकी गारंटी नहीं है। बैकस्लैश विस्तार का पलायन चरित्र है और समस्या यहाँ है। इसके अलावा विस्तार का व्यवहार shoptविकल्पों के साथ संबंधित है , इसलिए हमें मामले को मामले से देखना शुरू करना चाहिए ...

  2. जब आप cd C:\Foo\Barअपने बैश शेल में स्ट्रिंग चिपकाते हैं, तो इसका विस्तार किया जाएगा और यह दुभाषिया के लिए दिखाई देगा cd C:FooBar; इस रूप में यह $_आंतरिक चर में भी संग्रहीत किया जाएगा ।
    यदि आप के बजाय चिपकाया cd "C:\Foo\Bar"या cd 'C:\Foo\Bar'में $_ चर आप खोजना चाहिए C:\Foo\Bar
    चूँकि एक पूरी लाइन पढ़ने के तुरंत बाद इतिहास का विस्तार किया जाता है, इससे पहले कि शेल इसे शब्दों में तोड़ दे, आपको कुछ बशीवाद के साथ इसका उपयोग शुरू करने के लिए लुभाया जा सकता है , कम या ज्यादा सादे, उदाहरण के लिए, कुछ व्युत्पत्ति के साथ (शायद जोड़कर :pया :q) "", पार्सिंग वगैरह ...)

    !!:0 ${_//\\/\/}

    यह याद रखने का क्षण है कि पथ और फ़ाइल नाम के साथ खेलना शुरू करना सुरक्षित नहीं है , खासकर यदि वे विंडोज़ क्लिपबोर्ड से आते हैं (सामान्य रूप से पृष्ठ क्योंls पढ़ा है ? पार्स नहीं ?) , यह अनिवार्य रूप से टैब का उपयोग करने की संभावना से संबंधित है, रिक्त स्थान और newlines फ़ाइल नाम और निर्देशिका वाले के लिए सही वर्ण ...)।
    इसके अलावा जब आप माउस से कैप्चर किए गए टेक्स्ट को पेस्ट करते हैं , तो आप एक अग्रणी स्थान भी पेस्ट कर सकते हैं। इससे बच सकते हैं कि आपका कमांड इतिहास में समाप्त हो जाएगा (यह शेल विकल्पों में से निर्भर करता है ...)। यदि ऐसा है तो आपका अनुसरण !!नियंत्रित नहीं होगा ... ( किसी अन्य उत्तर में एक उदाहरण देखें )।यह एक अनावश्यक मूर्त जोखिम है

निष्कर्ष

इतिहास विस्तार इतिहास सूची के शब्दों को इनपुट स्ट्रीम में पेश करता है, जिससे कमांड्स को दोहराना आसान हो जाता है, पिछले इनपुट में आर्ग्युमेंट्स को मौजूदा इनपुट लाइन में डालें या पिछली कमांड्स में त्रुटियों को जल्दी से ठीक करें।

अगर यह आसान नहीं है तो मुझे लगता है कि हम कुछ गलत कर रहे हैं ;-)


Ad nauseam: थोड़ा सा प्रयोग

मैंने histverifyशेल में सक्षम किया है ...

shopt -s histverify
echo C:\Foo\Bar
!!:s|C|D| {1,2}A

फिर मैं प्रेस करता हूं Enterऔर सत्यापित विस्तार के रूप में

echo D:\Foo\Bar {1,2}A

फिर मैं Enterफिर से दबाता हूं और यह गूँजता है

D:FooBar 1A 2A

यह इंगित करता है कि ब्रेस विस्तारsubstitution failed से पहले संसाधित इतिहास विस्तार में उत्पन्न होता है , इसलिए सबसे पहले , और यह पुष्टि करता है कि इतिहास संशोधक ने चरित्र के प्रतिस्थापन को वास्तविक रीगेक्स के रूप में संसाधित नहीं किया (अभी तक) । ..s\


2

आप sedपरिणाम को बदलने और निष्पादित करने के लिए उपयोग कर सकते हैं ।

इस तरह के कमांड के लिए कई संभावित वेरिएंट हैं, लेकिन मेरे बैश पर केवल इस एक ने काम किया:

A=$(echo "!!\\" | sed 's,\\,/,g');eval $A

\\जोड़ा जाता है करने के लिए !!पिछले आदेश एक बैकस्लैश के साथ समाप्त मामले में है। इसके बिना, शेल भ्रमित हो जाएगा और लाइन की निरंतरता के लिए पूछेगा।

आप इसे फ़ाइल में बैश फ़ंक्शन के रूप में भी जोड़ सकते हैं ~/.bashrc:

function slash {
   A=$(history | tail -n 2 | head -n 1 | cut -c 8- | sed 's,\\,/,g')
   eval $A
}

यहाँ विंडोज पर मेरे बैश पर यह काम किया गया है:

दे घुमा के

यह समझने के लिए कि A=कमांड शेल चर के लिए सही मान कैसे प्रदान करता है A:

  • tailकमांड इतिहास से अंतिम दो पंक्तियाँ लेता है, जो cd \mnt\cबाद में slashस्वयं की पंक्तियाँ देता है। के भाग के history | tail -n 2रूप में भी लिखा जा सकता है history 2
  • head पहली पंक्ति जो है cd \mnt\c
  • cut द्वारा आपूर्ति लाइन-संख्या में कटौती history
  • sed सभी विरोधी स्लैश को स्लैश द्वारा प्रतिस्थापित करता है
  • eval चर की सामग्री को क्रियान्वित करता है A

हाय हैरी। यह कहने के लिए क्षमा करें कि मेरे GNU बैश संस्करण 4.3.11 पर (1) A=$(echo "!!\\" | sed 's,\\,/,g');eval $Aजब बैकस्लैश के साथ कमांड समाप्त होता है तो काम नहीं करता है। आपको एक स्थान जोड़ने के लिए मजबूर किया जाता है, उदाहरण के लिए C:\Foo\Bar\ , जैसा कि आपने कहा था, शेल लाइन की निरंतरता के लिए इंतजार करेगा। आप दो बार एंटर भी दबा सकते हैं। पहले मामले में आप प्राप्त करते हैं C:/Foo/Bar /( /दूसरे से पहले एक जगह के साथ ; दूसरे में यह एक त्रुटि उत्पन्न करेगा। फ़ंक्शन ठीक काम करता है।
हस्त्तूर

मैंने फ़ंक्शन लिखा क्योंकि (1) इसका उपयोग करना बहुत आसान है, और (2) वन-लाइनर बहुत कार्यान्वयन-निर्भर लग रहा था।
ry17 की

-1

मुझे नहीं लगता कि आप ऐसा कर सकते हैं। आपको फिर से कॉपी / पेस्ट करने की आवश्यकता है।

मुद्दा स्लैश बीइंग से भी संबंधित नहीं है, जो विकल्प कमांड विभाजक है, क्योंकि स्थानापन्न कमांड किसी भी विभाजक को स्वीकार करता है। इस मुद्दे को प्रतिस्थापित करने के लिए बैक-स्लैश के बारे में है, जो पहले से ही अपने अधिकार पर चरित्र के सरल बेकार पलायन के रूप में माना गया है।

इसलिए, जब आप स्थानापन्न कमांड कहते हैं, तो बैकस्लैश को पहले ही स्रोत से गायब कर दिया जाता है। बस कमांड को फिर से कॉल करने की कोशिश करें जैसा कि है ( !!)। सहित सटीक एक ही कमांड को प्रिंट करने के बजाय c:\foo, यह कमांड माइनस को पहले से संसाधित बैकस्लैश को निष्पादित करेगा, जिसके परिणामस्वरूप c:foo

और स्पष्ट रूप से आप एक लापता चरित्र को नहीं ढूंढ सकते हैं और न ही बदल सकते हैं। ऐसा करने की कोशिश में एक त्रुटि होगी।


1
कुंआ। यह अंत में गलत है क्योंकि यह परीक्षण वास्तव में काम करता है: echo c:\Fooइसके बाद !!:gs,F,\\f,। लेकिन बैकस्लैश से बच निकलने का अपने आप में दर्द होना प्रतीत होता है।
ए। लोइसो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.