गैर-रिक्त रिटर्न पर एक पाइप सशर्त बनाएं


16

वहाँ पाइप के लिए एक रास्ता एक से दूसरे फ़ंक्शन के परिणाम है, लेकिन तभी है एक निर्गम?


जवाबों:


9

निम्न ifnotemptyफ़ंक्शन इसके इनपुट को कमांड में देता है जो एक तर्क के रूप में पारित किया गया है, सिवाय इसके कि यह इनपुट खाली होने पर कुछ भी नहीं करता है। इसे लिखने के लिए पाइप source --fooमें उपयोग करें ।sink --barsource --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
}

डिजाइन नोट:

  • मैं उम्मीद करता हूं कि यह कार्यान्वयन सभी POSIX / Unix प्लेटफार्मों पर काम करेगा, हालांकि कड़ाई से यह मानक-अनुरूप नहीं है: यह ddउसके मानक इनपुट पर पढ़ने के लिए बताए गए एक से अधिक बाइट को नहीं पढ़ने पर निर्भर करता है ।
  • मुझे लगता है कि लिनक्स पर head -c 1एक उपयुक्त प्रतिस्थापन होगा dd 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 सीमा बढ़ाएँ :)


yourothercommandका आउटपुट कभी नहीं देखता है yourcommand
अगली सूचना तक रोक दिया गया।

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