वहाँ पाइप के लिए एक रास्ता एक से दूसरे फ़ंक्शन के परिणाम है, लेकिन तभी है एक निर्गम?
वहाँ पाइप के लिए एक रास्ता एक से दूसरे फ़ंक्शन के परिणाम है, लेकिन तभी है एक निर्गम?
जवाबों:
निम्न 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
एक उपयुक्त प्रतिस्थापन होगा 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)
इसलिए नहीं लिख सकते क्योंकि यदि पहला वर्ण एक नई पंक्ति है, तो कमांड प्रतिस्थापन अंतिम पंक्ति को खींच देगा, जिससे खाली इनपुट और इनपुट के बीच अंतर करना असंभव हो जाता है।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
}
यह आपके लिए काम करना चाहिए
$ --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.
नीचे दिया गया कार्य 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
स्वीकृत उत्तर से कार्य मेरे लिए कुछ भी भागने के बिना भी काम करता है।
कम से कम कुछ इस तरह काम करता है:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
कृपया ध्यान दें कि उपर्युक्त लाइन फ़ीड और आउटपुट के रूप में अन्य विशेष वर्णों पर विचार करेगा, इसलिए एक खाली लाइन उस पर पारित हो जाती है यदि कथन को आउटपुट माना जाएगा। अगर आपकी आउटपुट आमतौर पर 1 बाइट से अधिक होनी चाहिए तो -gt सीमा बढ़ाएँ :)
yourothercommand
का आउटपुट कभी नहीं देखता है yourcommand
।
इसके बजाय 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