খালি খালি রিটার্নে পাইপকে শর্তযুক্ত করুন


16

সেখানে পাইপ একটি উপায় অন্য এক ফাংশন আউটপুট, কিন্তু শুধুমাত্র যদি হয় একটি আউটপুট?


উত্তর:


9

নিম্নলিখিত ifnotemptyফাংশনটি আর্গুমেন্ট হিসাবে পাস কমান্ডটিতে তার ইনপুটটি পাইপ করে, ইনপুট খালি থাকলে এটি কিছুই করে না। নল এটি ব্যবহার করার জন্য source --fooবা sink --barলেখা দ্বারা source --foo | pipe_if_not_empty sink --bar

pipe_if_not_empty () {
  head=$(dd bs=1 count=1 2>/dev/null; echo a)
  head=${head%a}
  if [ "x$head" != x"" ]; then
    { printf %s "$head"; cat; } | "$@"
  fi
}

নকশা নোট:

  • আমি আশা করি এই বাস্তবায়নটি সমস্ত পসিক্স / ইউনিক্স প্ল্যাটফর্মগুলিতে কাজ করবে, যদিও কঠোরভাবে বলা এটি মান-সম্মতিজনক নয়: এটি ddতার স্ট্যান্ডার্ড ইনপুটটিতে যে বাইটটি পড়তে বলেছে তার চেয়ে বেশি না পড়ার উপর নির্ভর করে ।
  • আমার ধারণা লিনাক্সের head -c 1জন্য উপযুক্ত প্রতিস্থাপন হবে thinkdd bs=1 count=1 2>/dev/null
  • অন্যদিকে, head -n 1উপযুক্ত হবে না কারণ headসাধারণত এটির ইনপুটটি বাফার করে এবং এটি যে রেখাটি আউটপুট করে তার চেয়ে বেশি পড়তে পারে - এবং যেহেতু এটি পাইপ থেকে পড়ছে, অতিরিক্ত বাইটগুলি কেবল হারিয়ে গেছে।
  • read -r headএবং এমনকি read -r -n 1 headএখানে উপযুক্ত নয় কারণ প্রথম অক্ষরটি যদি একটি নতুন লাইন headহয় তবে খালি স্ট্রিংয়ে সেট করা হবে, খালি ইনপুট এবং ফাঁকা লাইন দিয়ে ইনপুটটির মধ্যে পার্থক্য করা অসম্ভব হয়ে পড়ে।
  • আমরা কেবল লিখতে পারি না head=$(head -c 1)কারণ যদি প্রথম অক্ষরটি একটি নতুন লাইন হয় তবে কমান্ড প্রতিস্থাপনটি চূড়ান্ত নিউলাইনটি কেটে ফেলবে, খালি ইনপুট এবং ফাঁকা লাইন দিয়ে ইনপুটটির মধ্যে পার্থক্য করা অসম্ভব করে তোলে।
  • ব্যাশ, ksh বা zsh, আপনি প্রতিস্থাপন করতে পারেন catদ্বারা </dev/stdinএকটি আণুবীক্ষণিক কর্মক্ষমতা লাভের জন্য।

আপনি মেমরি পুরো অন্তর্বর্তী ডেটা সঞ্চয় করার কিছু মনে না করেন, এখানে খুব সামান্য সহজ বাস্তবায়ন pipe_if_not_empty

pipe_if_not_empty () {
  input=$(cat; echo a);
  if [ "x$input" != x"a" ]; then
    { printf %s "${input%a}"; } | "$@"
  fi
}

নিম্নলিখিত সতর্কতাগুলির সাথে এখানে একটি সামান্য সরল বাস্তবায়ন:

  • উত্স দ্বারা উত্পাদিত ডেটা খালি বিবেচনা করা হয় যদি এবং কেবলমাত্র এটি সম্পূর্ণরূপে নিউলাইন চরিত্রগুলি নিয়ে থাকে। (এটি বাস্তবে কাম্য হতে পারে))
  • সিঙ্কে খাওয়ানো ডেটা ঠিক একটি নিউলাইন চরিত্রের সাথে শেষ হয়, উত্স দ্বারা উত্পাদিত ডেটা কতগুলি নতুন লাইনের সাথে শেষ হয় তা নয়। (এটি একটি সমস্যা হতে পারে।)

আবার পুরো ডেটা মেমোরিতে জমা থাকে।

pipe_if_not_empty () {
  input=$(cat);
  if [ "x$input" != x"" ]; then
    { printf '%s\n' "${input}"; } | "$@"
  fi
}

17

এটি আপনার পক্ষে কাজ করা উচিত

$ --a function-- | [ xargs -r ] --another function--

একটি উদাহরণ

$ echo -e "\n\n" | xargs -r ls
$ # No output. ls did not run.
$ echo -e "\n\n1" | xargs -r ls
ls: cannot access 1: No such file or directory

এটি সহজ তবে এটি আপনার পক্ষে কাজ করা উচিত। যদি আপনার "একটি ফাংশন" খালি স্ট্রিং বা পাইপলাইনের নীচে একটি নতুন লাইন প্রেরণ করে, xargs -r, "অন্য ফাংশন" এর মাধ্যমে উত্তরণকে আটকাবে।

Xargs এর জন্য রেফারেন্স: http://www.oreillynet.com/linux/cmd/cmd.csp?path=x/xargs

-r, --no-run-if-empty
Do not run command if standard input contains only blanks.


4

নীচের ফাংশনটি 1 ম বাইট পড়ার চেষ্টা করে এবং যদি সাফল্যপূর্ণ ইকো থাকে যা বাকিট এবং বিড়ালগুলি বাকী করে। দক্ষ এবং 100% পোর্টেবল হওয়া উচিত।

if_read() {
    IFS="" read -rN 1 BYTE && { echo -nE "$BYTE"; cat; } | "$@";
}

পরীক্ষার কেস:

$ echo -n | if_read wc -c
$ echo | if_read wc -c
1
$ echo -en "\nX" | if_read wc -c
2
$

আমি চালানোর সময় এই ফাংশনটি আমার জন্য ব্যর্থ হয় echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" foo@bar.com। এটি এটি মনে করে lineএবং hereউভয়ই ই-মেইলের প্রাপক, বিষয়টিতে টোকেন নয়। বিষয়টি কাজে লাগানোর জন্য আমাকে "আশেপাশে পালাতে হবে। যাইহোক, pipe_if_not_emptyগৃহীত উত্তর থেকে ফাংশনটি কোনও কিছু ছাড়িয়েও আমার পক্ষে কাজ করে।
কুজুরুর

2

কমপক্ষে এর মতো কিছু কাজ করে:

yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi

দয়া করে নোট করুন যে উপরেরটি লাইন ফিড এবং অন্যান্য বিশেষ অক্ষরকে আউটপুট হিসাবে বিবেচনা করবে, সুতরাং যদি একটি বিবৃতি আউটপুট হিসাবে বিবেচিত হবে তবে একটি ফাঁকা লাইন চলে গেছে। আপনার আউটপুটটি সাধারণত 1 বাইটের বেশি হওয়া উচিত যদি কেবলমাত্র -gt সীমা বাড়ান :)



2

পরিবর্তে sender | receiver:

tester () { local a=$(</dev/stdin); if [[ $a ]]; then printf '%s\n' "$a" | receiver; fi; }
sender | tester

অথবা আপনি গিলের জবাব হিসাবে যেমনটি আর্গুমেন্ট হিসাবে গ্রহণযোগ্য প্রোগ্রামটিকে গ্রহণ করার জন্য এটি পরিবর্তন করে এটি আরও সাধারণ উদ্দেশ্য করতে পারেন:

tester () { local a=$(</dev/stdin); if [[ $a ]]; then printf '%s\n' "$a" | "$@"; fi; }
sender | tester receiver
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.