কোনও স্ক্রিপ্ট কীভাবে লিখবেন যা কোনও ফাইল থেকে বা স্টিডিনের ইনপুট গ্রহণ করে?


56

কীভাবে একজন এমন কোনও স্ক্রিপ্ট লিখতে পারেন যা কোনও ফাইল নাম যুক্তি বা স্টিডিনের কাছ থেকে ইনপুট গ্রহণ করে?

উদাহরণস্বরূপ, আপনি lessএইভাবে ব্যবহার করতে পারেন । এক চালানো less filenameএবং সমতুল্য করতে পারেন cat filename | less

এটি করার সহজ উপায় কি "বাক্সের বাইরে" আছে? নাকি আমার চাকাটি পুনরায় উদ্ভাবন করা এবং স্ক্রিপ্টে কিছুটা যুক্তি লেখার দরকার আছে?


@ প্লাজমাপাওয়ার যতক্ষণ এই প্রশ্নটি এসইউতে বিষয়-ই-বিষয় অবধি রয়েছে, ততক্ষণ আলাদা এসই সাইটে জিজ্ঞাসা করার প্রয়োজন নেই । অনেকগুলি এসই সাইটের ওভারল্যাপ রয়েছে; সাধারণত প্রশ্নটি অফ-টপিক (যে ক্ষেত্রে মাইগ্রেটেড করার পক্ষে ভোট দেওয়া হয়) বা অন-টপিক না হয় তবে বেশি পরিমাণে সাড়া না পাওয়া পর্যন্ত আমাদের একটি ওভারল্যাপিং সাইটের পরামর্শ দেওয়ার প্রয়োজন নেই (এই ক্ষেত্রে, প্রশ্নকারীকে মডারেটরের পক্ষে পতাকাঙ্কিত করা উচিত - মনোযোগ / মাইগ্রেশন, ক্রস-পোস্ট নয়)।
বব

উত্তর:


58

ফাইল আর্গুমেন্টটি যদি আপনার স্ক্রিপ্টের প্রথম আর্গুমেন্ট হয় তবে পরীক্ষা করুন যে সেখানে একটি আর্গুমেন্ট রয়েছে ( $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) এবং (-এ অপারেটর) প্রথম আর্গুমেন্টটি একটি ফাইল হয় (-f পরীক্ষা যদি "$ 1" একটি ফাইল হয়) তবে পরীক্ষার ফলাফলটি সত্য।

&&শেল লজিকাল এবং অপারেটর। যদি পরীক্ষাটি সত্য হয়, তবে নির্ধারণ করুন input="$1"এবং cat $inputফাইলটি আউটপুট দেবেন।

||শেল লজিকাল ওআর অপারেটর। যদি পরীক্ষাটি মিথ্যা হয়, তবে নিম্নলিখিত কমান্ডগুলি ||পার্স করা হবে। ইনপুট "-" বরাদ্দ করা হয়। কমান্ডটি cat -কীবোর্ড থেকে পড়ে।

সংক্ষিপ্তসার হিসাবে, যদি স্ক্রিপ্ট আর্গুমেন্ট সরবরাহ করা হয় এবং এটি একটি ফাইল হয়, তবে ভেরিয়েবল ইনপুট ফাইলের নামে বরাদ্দ করা হয়। যদি কোনও বৈধ যুক্তি না থাকে তবে বিড়াল কীবোর্ড থেকে পড়ে।


কি করে && input="$1" || input="-" এবং কেন এটি testঅপারেটরের বাইরে ?
সিএমও

আমি কিছু ব্যাখ্যা সহ একটি সম্পাদনা যুক্ত করেছি যা আশা করি সহায়তা করবে।
সন্দেহভাজন

স্ক্রিপ্টে একাধিক যুক্তি ( $@) থাকলে কী হবে?
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 man পৃষ্ঠা একটি চমত্কার সংক্ষিপ্ত ব্যাখ্যা করেছেন 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

দ্রষ্টব্য: জেডএসএইচ এবং কেএসএইচ (এবং সম্ভবত অন্যরা) প্রম্পটের জন্য আলাদা সিনট্যাক্স ব্যবহার করে:

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একটি পরীক্ষার স্ক্রিপ্টে অনুলিপি করেছি এবং এটি একটি ত্রুটি বার্তা দেয় কারণ আদেশটি অজানা own টর্স ফর্ম একই।
সুজানা

1
@ সুজানা_ কে: আপনি কোন শেল ব্যবহার করছেন? যদি এটি সত্য হয় তবে এটি পসিক্স শ কমান্ড / বোর্ন শেলটির কার্যকরী বাস্তবায়ন নয়।
আর ..

লিনাক্স মিন্ট কিয়ানাতে জিএনইউ বাশ 4.3.11
সুজানা

3

ইতিমধ্যে এইভাবে আচরণ করে এমন অন্য কিছু ব্যবহার করুন (বা চেইন অফ অফ) and "$@"

ধরা যাক আমি এমন একটি সরঞ্জাম লিখতে চাই যা ট্যাবগুলির সাহায্যে পাঠ্যের ফাঁকে ফাঁকে ফাঁকে স্থান দেয় replace

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এবং এটি আশ্চর্যজনকভাবে কাজ করে!
fregante

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

সবচেয়ে সহজ উপায় এবং পসিএক্স অনুগত:

file=${1--}

যা সমান ${1:--}

তারপরে যথারীতি ফাইলটি পড়ুন:

while IFS= read -r line; do
  printf '%s\n' "$line" # Or: env POSIXLY_CORRECT=1 echo "$line"
done < <(cat -- "$file")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.