बैश स्क्रिप्ट में `read` से वेरिएबल्स अपरिभाषित हैं


0

मेरे पास यह बैश स्क्रिप्ट है जिसका मैं उपयोग करता हूं i3wm स्क्रीन मोड (बाहरी स्क्रीन, आंतरिक स्क्रीन, सभी या दर्पण) के बीच टॉगल करने के लिए। स्क्रिप्ट का पहला भाग स्क्रीन के नाम को पकड़ लेता है। यदि मैं एक टर्मिनल में निम्नलिखित भाग और रन की प्रतिलिपि बनाता हूं:

#!/bin/bash

xrandr|grep " connected primary"|IFS=" " read INTERNAL_OUTPUT con
xrandr|awk '/ connected/ && !/ primary/'|IFS=" " read EXTERNAL_OUTPUT con
echo internal monitor is $INTERNAL_OUTPUT
echo external monitor is $EXTERNAL_OUTPUT

...

मुझे कुछ मिलता है

$ ./script.sh
internal monitor is eDPI
external monitor is DPI-1

लेकिन जब मैं वास्तविक स्क्रिप्ट चलाता हूं, तो चर खाली होते हैं और मुझे जो दिखता है वह सब होता है

$ ./script.sh
internal monitor is 
external monitor is 

किसी स्क्रिप्ट के अंदर चर सेट करते समय क्या अंतर होता है?


1
अगर द echo कमांड स्क्रिप्ट के समान ही हैं read कमांड उन्हें काम करना चाहिए, लेकिन जब तक आप इसे नहीं कहते तब तक वे स्क्रिप्ट के बाहर काम नहीं करेंगे . / source आदेश।
AFH

मुझे समझ नहीं आ रहा है कि आपका क्या मतलब है। इको सहित स्क्रिप्ट के अंदर पूरी बात है, लेकिन यह काम नहीं करता है। चर अभी भी खाली हैं।
ecc

उस स्थिति में मैं यह नहीं देख सकता कि यह टर्मिनल से कैसे काम कर सकता है: मेरे काम करने का एकमात्र तरीका यही है xrandr|grep " connected primary"|{ IFS=" " read INTERNAL_OUTPUT con; echo internal monitor is $INTERNAL_OUTPUT; }, और इसी तरह अन्य मॉनिटर के लिए। यह टर्मिनल और एक स्क्रिप्ट दोनों में काम करता है।
AFH

2
वे मेरे लिए एक टर्मिनल में भी काम नहीं करते ... परिकल्पना: यह काम नहीं करेगा bash, और आपका कंसोल नहीं है bash (इसलिए वे वहां काम करते हैं) (क्या कहते हैं ls -l /proc/$$/exe?) लेकिन आपकी स्क्रिप्ट को बैश (शेबंग के कारण) की आवश्यकता होती है इसलिए बैश नियमों का उपयोग करता है और इससे कोड विफल हो जाता है।
xenoid

यदि आप में एक चर सेट करना चाहते हैं bash, आपको कुछ चाहिए INTERNAL_OUTPUT=$(xrandr|grep " connected "|grep -o '^[^ ]*')। यह बनाता है INTERNAL_OUTPUT स्क्रिप्ट में बाद की लाइनों पर उपलब्ध है, हालांकि टर्मिनल पर लौटने पर नहीं जब तक कि साथ नहीं बुलाया जाता .। यदि आप एक स्क्रिप्ट को चालू शेल में चर को कॉल किए बिना सेट करना चाहते हैं . आपको इसे एक फंक्शन के रूप में कोड करना होगा।
AFH

जवाबों:


2

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

इसके आस-पास पाने के लिए आप @AFH कहते हैं और कमांड को बदल सकते हैं, इसलिए केवल जो आप प्रिंट करना चाहते हैं, उसे असाइन करें और पेरेंट शेल में एक वैरिएबल को असाइन करें।

वैकल्पिक रूप से, आप कमांड्स को रिस्ट्रक्चर कर सकते हैं ताकि आप रीडिंग में पाइपिंग न करें। मैं AFH के दृष्टिकोण को पसंद करूंगा, लेकिन पुन: क्रमबद्धता जैसा दिख सकता है:

IFS=" " read INTERNAL_OUTPUT con < <(xrandr|grep " connected primary")

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

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