एक स्क्रिप्ट कैसे लिखें जो एक फ़ाइल से या स्टड से इनपुट स्वीकार करता है?


57

कोई एक स्क्रिप्ट कैसे लिख सकता है जो किसी फ़ाइल नाम तर्क से या स्टड से इनपुट स्वीकार करता है?

उदाहरण के लिए, आप lessइस तरह से उपयोग कर सकते हैं । एक निष्पादित less filenameऔर समकक्ष हो सकता है cat filename | less

क्या ऐसा करने के लिए "बॉक्स से बाहर" एक आसान तरीका है? या क्या मुझे पहिया का फिर से आविष्कार करने और स्क्रिप्ट में थोड़ा तर्क लिखने की आवश्यकता है?


@PlasmaPower जब तक एसयू पर सवाल का विषय है, तब तक अलग एसई साइट पर पूछने की कोई आवश्यकता नहीं है । बहुत सी एसई साइटों में ओवरलैप होता है; आम तौर पर हमें ओवरलैपिंग साइट पर सुझाव देने की आवश्यकता नहीं है, जब तक कि सवाल ऑफ-टॉपिक (किस मामले में, वोट माइग्रेट करने के लिए) या ऑन-टॉपिक नहीं है, लेकिन बहुत अधिक प्रतिक्रिया नहीं मिल रही है (किस मामले में, पूछने वाले को मॉडरेटर के लिए झंडा लगाना चाहिए- ध्यान / प्रवास, क्रॉस-पोस्ट नहीं)।
बॉब

जवाबों:


59

यदि फ़ाइल तर्क आपकी स्क्रिप्ट का पहला तर्क है, तो परीक्षण करें कि एक तर्क है ( $1) और यह एक फ़ाइल है। स्टड से एल्स रीड इनपुट -

तो आपकी स्क्रिप्ट में कुछ ऐसा हो सकता है:

#!/bin/bash
[ $# -ge 1 -a -f "$1" ] && input="$1" || input="-"
cat $input

उदाहरण के लिए फिर आप स्क्रिप्ट को कॉल कर सकते हैं

./myscript.sh filename

या

who | ./myscript.sh

स्क्रिप्ट की कुछ व्याख्या संपादित करें :

[ $# -ge 1 -a -f "$1" ]- यदि कम से कम एक कमांड लाइन तर्क ( $# -ge 1) और (-a ऑपरेटर) पहला तर्क एक फ़ाइल है (-f परीक्षण यदि "$ 1" एक फ़ाइल है) तो परीक्षण का परिणाम सही है।

&&खोल तार्किक और ऑपरेटर है। यदि परीक्षण सत्य है, तो असाइन करें input="$1"और cat $inputफ़ाइल को आउटपुट करेंगे।

||खोल तार्किक या ऑपरेटर है। यदि परीक्षण गलत है, तो निम्नलिखित आदेश ||पार्स किए जाते हैं। इनपुट "-" को सौंपा गया है। कमांड cat -कीबोर्ड से पढ़ता है।

संक्षेप में, यदि स्क्रिप्ट तर्क प्रदान किया गया है और यह एक फ़ाइल है, तो चर इनपुट फ़ाइल नाम को सौंपा गया है। यदि कोई मान्य तर्क नहीं है, तो बिल्ली कीबोर्ड से पढ़ती है।


क्या करता && input="$1" || input="-" है और यह testऑपरेटर के बाहर क्यों है ?
cmo

मैंने कुछ स्पष्टीकरण के साथ एक संपादन जोड़ा है जो मुझे आशा है कि मदद करेगा।
शक

क्या होगा यदि स्क्रिप्ट में कई तर्क ( $@) हों?
g33kz0r

12

readमानक इनपुट से पढ़ता है। इसे फ़ाइल ( ./script <someinput) या पाइप ( dosomething | ./script) के माध्यम से रीडायरेक्ट करने से यह अलग तरीके से काम नहीं करेगा।

आपको बस इतना करना है कि इनपुट में सभी लाइनों के माध्यम से लूप करना है (और यह फ़ाइल में लाइनों पर पुनरावृति करने से अलग नहीं है)।

(नमूना कोड, केवल एक पंक्ति प्रक्रियाएं)

#!/bin/bash

read var
echo $var

(या तो के माध्यम से अपने मानक इनपुट की पहली पंक्ति गूंज होगा <या |)।


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

4

आप उल्लेख नहीं करते हैं कि आप किस शेल का उपयोग करने की योजना बना रहे हैं, इसलिए मैं बैश मानूंगा, हालांकि ये गोले भर में मानक चीजें हैं।

फ़ाइल तर्क

तर्क चर के माध्यम से पहुँचा जा सकता है $1- $n( $0प्रोग्राम को चलाने के लिए प्रयुक्त कमांड देता है)। कहो कि मेरे पास एक स्क्रिप्ट है जो सिर्फ catउन दोनों के बीच एक सीमांकक के साथ एन फाइलों की संख्या है:

#!/usr/bin/env bash
#
# Parameters:
#    1:   string delimiter between arguments 2-n
#    2-n: file(s) to cat out
for arg in ${@:2} # $@ is the array of arguments, ${@:2} slices it starting at 2.
do
   cat $arg
   echo $1
done

इस मामले में, हम बिल्ली के लिए एक फ़ाइल नाम दे रहे हैं। हालाँकि, यदि आप फ़ाइल में डेटा बदलना चाहते हैं (बिना स्पष्ट रूप से लिखे और इसे फिर से लिखना), तो आप फ़ाइल सामग्री को एक चर में संग्रहीत कर सकते हैं:

file_contents=$(cat $filename)
[...do some stuff...]
echo $file_contents >> $new_filename

स्टडिन से पढ़ें

जहाँ तक स्टड से पढ़ने की बात है, ज्यादातर गोले में एक मानक स्तर का निर्माण होता है read, हालांकि इस बात में मतभेद हैं कि संकेतों को कैसे निर्दिष्ट किया जाता है (बहुत कम से कम)।

बैश builtins आदमी पेज की एक बहुत संक्षिप्त व्याख्या है read, लेकिन मैं पसंद करते हैं बैश हैकर्स पेज।

सीधे शब्दों में:

read var_name

एकाधिक चर

एकाधिक चर सेट करने के लिए, बस कई पैरामीटर नाम प्रदान करें read:

read var1 var2 var3

read तब प्रत्येक चर में एक शब्द स्टड से, शेष सभी शब्दों को अंतिम चर में डंप कर देगा।

λ read var1 var2 var3
thing1 thing2 thing3 thing4 thing5
λ echo $var1; echo $var2; echo $var3
thing1
thing2
thing3 thing4 thing5

यदि चर की तुलना में कम शब्द दर्ज किए जाते हैं, तो बचे हुए चर खाली हो जाएंगे (भले ही पहले सेट हो):

λ read var1 var2 var3
thing1 thing2
λ echo $var1; echo $var2; echo $var3
thing1
thing2
# Empty line

संकेतों

मैं -pअक्सर एक संकेत के लिए ध्वज का उपयोग करता हूं :

read -p "Enter filename: " filename

नोट: ZSH और KSH (और शायद अन्य) संकेतों के लिए एक अलग वाक्यविन्यास का उपयोग करते हैं:

read "filename?Enter filename: " # Everything following the '?' is the prompt

डिफ़ॉल्ट मान

यह वास्तव में एक readचाल नहीं है, लेकिन मैं इसके साथ संयोजन के रूप में उपयोग करता हूं read। उदाहरण के लिए:

read -p "Y/[N]: " reply
reply=${reply:-N}

मूल रूप से, यदि चर (उत्तर) मौजूद है, तो स्वयं वापस लौटें, लेकिन यदि रिक्त है, तो निम्न पैरामीटर ("एन") लौटाएं।


4

सबसे सरल तरीका यह है कि आप अपने आप को स्टड पुनर्निर्देशित करें:

if [ "$1" ] ; then exec < "$1" ; fi

या यदि आप अधिक संक्षिप्त रूप पसंद करते हैं:

test "$1" && exec < "$1"

अब आपकी बाकी स्क्रिप्ट सिर्फ स्टड से पढ़ी जा सकती है। बेशक, आप फ़ाइल नाम की स्थिति को हार्ड-कोडिंग करने के बजाय अधिक उन्नत विकल्प पार्सिंग के साथ भी कर सकते हैं "$1"


execतर्क को एक कमांड के रूप में निष्पादित करने का प्रयास करेंगे जो कि हम यहां नहीं चाहते हैं।
सुजाना

@ सुजाना_के: नहीं जब इसके पास कोई तर्क नहीं है, तो यहां की तरह। उस स्थिति में यह केवल एक बच्चे की प्रक्रिया के बजाय शेल के लिए फ़ाइल डिस्क्रिप्टर को प्रतिस्थापित करता है।
आर .. २

मैंने if [ "$1" ] ; then exec < "$1" ; fiएक टेस्ट स्क्रिप्ट में कॉपी किया और यह एक त्रुटि संदेश देता है क्योंकि कमांड अनकाउन्टेड है। समान रूप के साथ।
सुजाना

1
@ सुजान_के: आप किस खोल का उपयोग कर रहे हैं? यदि यह सच है तो यह POSIX sh कमांड / बॉर्न शेल का कार्यशील कार्यान्वयन नहीं है।
आर ..

लिनक्स मिंट Qiana पर GNU बैश 4.3.11
सुजाना

3

उपयोग (या श्रृंखला बंद) कुछ और जो पहले से ही इस तरह से व्यवहार करता है, और उपयोग करता है "$@"

मान लें कि मैं एक उपकरण लिखना चाहता हूं जो टैब्स के साथ पाठ में रिक्त स्थान के रनों को बदल देगा

trऐसा करने का सबसे स्पष्ट तरीका है, लेकिन यह केवल स्टड को स्वीकार करता है, इसलिए हमें इसे बंद करना होगा cat:

$ cat entab1.sh
#!/bin/sh

cat "$@"|tr -s ' ' '\t'
$ cat entab1.sh|./entab1.sh
#!/bin/sh

cat     "$@"|tr -s      '       '       '\t'
$ ./entab1.sh entab1.sh
#!/bin/sh

cat     "$@"|tr -s      '       '       '\t'
$ 

एक उदाहरण के लिए जहां पहले से ही इस्तेमाल किया जा रहा उपकरण इस तरह से व्यवहार करता है, हम sedइसके बजाय इसे फिर से लागू कर सकते हैं :

$ cat entab2.sh
#!/bin/sh

sed -r 's/ +/\t/g' "$@"
$ 

3

आप भी कर सकते हैं:

#!/usr/bin/env bash

# Set variable input_file to either $1 or /dev/stdin, in case $1 is empty
# Note that this assumes that you are expecting the file name to operate on on $1
input_file="${1:-/dev/stdin}"

# You can now use "$input_file" as your file to operate on
cat "$input_file"

बैश में अधिक साफ पैरामीटर प्रतिस्थापन टोटके के लिए, यह देखें ।


1
यह शानदार है! मैं उपयोग कर रहा हूँ uglifyjs < /dev/stdinऔर यह अद्भुत काम करता है!
शाम

0

आप इसे सरल भी रख सकते हैं और इस कोड का उपयोग कर सकते हैं


जब आप इस कोड के साथ एक स्क्रिप्ट फ़ाइल pass_it_on.sh बनाते हैं ,

#!/bin/bash

cat

तुम दौड़ सकते हो

cat SOMEFILE.txt | ./pass_it_on.sh

और स्टडिन की सभी सामग्री बस स्क्रीन पर उगल दी जाएगी।


वैकल्पिक रूप से इस कोड का उपयोग दोनों एक फ़ाइल में स्टडिन की एक प्रति रखने के लिए करते हैं और फिर इसे स्क्रीन पर भेजते हैं।

#!/bin/bash

tmpFile=`mktemp`
cat > $tmpFile
cat $tmpFile    

और यहाँ एक और उदाहरण है, शायद अधिक पठनीय, यहाँ समझाया गया है:

http://mockingeye.com/blog/2013/01/22/reading-everything-stdin-in-a-bash-script/

#!/bin/bash

VALUE=$(cat)

echo "$VALUE"

मज़े करो।

RaamEE


0

सबसे सरल तरीका और POSIX अनुपालन है:

file=${1--}

के बराबर है ${1:--}

फिर फ़ाइल को हमेशा की तरह पढ़ें:

while IFS= read -r line; do
  printf '%s\n' "$line" # Or: env POSIXLY_CORRECT=1 echo "$line"
done < <(cat -- "$file")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.