Boru için bir yol başka bir fonksiyonun çıkışı var mı, ama sadece orada olduğunu bir çıkış?
Boru için bir yol başka bir fonksiyonun çıkışı var mı, ama sadece orada olduğunu bir çıkış?
Yanıtlar:
Aşağıdaki ifnotempty
işlev, girdiyi bağımsız değişken olarak iletilen komuta bağlar, ancak giriş boşsa hiçbir şey yapmaz. Boru için kullanın source --foo
içine sink --bar
yazı ile 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
}
Tasarım notları:
dd
standart girdisinde okuması söylenen bir bayttan daha fazla okumaya dayanmaz.head -c 1
için uygun bir yedek olacağını düşünüyorum dd bs=1 count=1 2>/dev/null
.head -n 1
için uygun olmaz head
- ve bir borudan okuduğundan, ekstra baytlar kaybolur.read -r head
ve hatta read -r -n 1 head
burada bile uygun değildir, çünkü ilk karakter yeni bir satırsa, head
boş dizeye ayarlanır ve boş giriş ile boş bir satırdan başlayarak girdi arasında ayrım yapılmasını imkansız hale getirir.head=$(head -c 1)
çünkü ilk karakter yeni satırsa, komut ikamesi son satırsonu çizgisini kaldırarak boş satır ile boş satırdan başlayarak girdi arasında ayrım yapmayı imkansız hale getirir.cat
tarafından </dev/stdin
mikroskobik bir performans kazancı için.Tüm ara verileri hafızada saklamak sakıncası yoksa, işte çok daha basit bir uygulama pipe_if_not_empty
.
pipe_if_not_empty () {
input=$(cat; echo a);
if [ "x$input" != x"a" ]; then
{ printf %s "${input%a}"; } | "$@"
fi
}
İşte aşağıdaki uyarılarla biraz daha basit bir uygulama:
Yine, tüm veriler bellekte saklanır.
pipe_if_not_empty () {
input=$(cat);
if [ "x$input" != x"" ]; then
{ printf '%s\n' "${input}"; } | "$@"
fi
}
Bu senin için çalışmalı
$ --a function-- | [ xargs -r ] --another function--
Bir örnek
$ 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
Çok basit ama sizin için işe yaramalı. Eğer "bir işlev" iniz boş bir dize veya hatta yeni bir satır gönderirse, xargs -r "başka bir işleve" geçişi önler.
Xargs için referans: 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.
Aşağıdaki işlev 1. baytı okumaya çalışır ve eğer başarılı olursa o bayt ve geri kalanını kediler. Verimli ve% 100 taşınabilir olmalıdır.
if_read() {
IFS="" read -rN 1 BYTE && { echo -nE "$BYTE"; cat; } | "$@";
}
Test senaryoları:
$ 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
. Konudaki belirteçleri değil, e-postanın alıcıları olduğunu line
ve here
her ikisinin de alıcı olduğunu düşünür . "
İşe başlamak için çevreden kaçmak zorundayım . Ancak, pipe_if_not_empty
kabul edilen cevabın işlevi hiçbir şeyden kaçmadan bile benim için çalışıyor.
En azından böyle bir şey işe yarıyor:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
Lütfen yukarıdakilerin satır beslemelerini ve diğer özel karakterleri çıktı olarak kabul edeceğini unutmayın, bu nedenle ifade bir çıktı olarak kabul edilecekse boş bir satır geçti. Çıktınız genellikle 1 bayttan yüksekse -gt sınırını yükseltin :)
yourothercommand
çıkışını asla görmez yourcommand
.
Yerine sender | receiver
:
tester () { local a=$(</dev/stdin); if [[ $a ]]; then printf '%s\n' "$a" | receiver; fi; }
sender | tester
Veya alma programını Gilles'in cevabındaki gibi bir argüman olarak kabul etmesini değiştirerek daha genel bir amaç haline getirebilirsiniz:
tester () { local a=$(</dev/stdin); if [[ $a ]]; then printf '%s\n' "$a" | "$@"; fi; }
sender | tester receiver