Boru kullanarak bash işlevleri nasıl oluşturulur?


18

Bu şekilde tanımlanan birkaç fonksiyonum var:

function f {
  read and process $1
  ...
  echo $result
}

Onları bir araya getirmek istiyorum, böylece çağırma gibi görünecektir f | g | h.

Bağımsız değişkenler üzerinde çalışan işlevi stdin'den bir okuma bağımsız değişkenine dönüştürmek için hangi deyimi kullanmalıyım? Akıştan bağımsız değişkenlerin çiftlerini, gruplarını okumaktan kaçınmak mümkün müdür (örn. Boş sonlandırma)?


Ya benzer bir şey istersiniz h(g(f(...)))ya da işlevlerin her biri standart girdi ( read x; ...) ' den okunur ve standart çıktıya ( echo ...) yazar .
vonbrand

Yanıtlar:


21

Potansiyel yaklaşımlardan biri while...read, işlevlerinize STDIN aracılığıyla işleve gelen tüm verileri işleyecek, üzerinde çalışacak ve daha sonra elde edilen verileri STDOUT aracılığıyla geri gönderecek bir yapı oluşturmak olacaktır.

function X {
  while read data; do
    ...process...
  done
}

while ..read..Bileşenlerinizi nasıl yapılandıracağınıza dikkat etmek gerekir, çünkü bunlar güvenilir bir şekilde tüketebilecekleri veri türlerine bağımlı olacaktır. Bulabileceğiniz en uygun yapılandırma olabilir.

Misal

$ logF() { while read data; do echo "[F:$(date +"%D %T")] $data"; done; }
$ logG() { while read data; do echo "G:$data";                    done; }
$ logH() { while read data; do echo "H:$data";                    done; }

İşte her işlev kendi başına.

$ echo "hi" | logF
[F:02/07/14 20:01:11] hi

$ echo "hi" | logG
G:hi

$ echo "hi" | logH
H:hi

İşte onları birlikte kullandığımız zamandır.

$ echo "hi" | logF | logG | logH
H:G:[F:02/07/14 19:58:18] hi

$ echo -e "hi\nbye" | logF | logG | logH
H:G:[F:02/07/14 19:58:22] hi
H:G:[F:02/07/14 19:58:22] bye

Çeşitli giriş stilleri alabilirler.

#-- ex. #1
$ cat <<<"some string of nonsense" | logF | logG | logH
H:G:[F:02/07/14 20:03:47] some string of nonsense

#-- ex. #2    
$ (logF | logG | logH) <<<"Here comes another string."
H:G:[F:02/07/14 20:04:46] Here comes another string.

#-- ex. #3
$ (logF | logG | logH)
Look I can even
H:G:[F:02/07/14 20:05:19] Look I can even
type to it
H:G:[F:02/07/14 20:05:23] type to it
live
H:G:[F:02/07/14 20:05:25] live
via STDIN
H:G:[F:02/07/14 20:05:29] via STDIN
..type Ctrl + D to stop..

#-- ex. #4
$ seq 5 | logF | logG | logH
H:G:[F:02/07/14 20:07:40] 1
H:G:[F:02/07/14 20:07:40] 2
H:G:[F:02/07/14 20:07:40] 3
H:G:[F:02/07/14 20:07:40] 4
H:G:[F:02/07/14 20:07:40] 5

#-- ex. #5
$ (logF | logG | logH) < <(seq 2)
H:G:[F:02/07/14 20:15:17] 1
H:G:[F:02/07/14 20:15:17] 2

4

Slm'nin cevabına bir ek olarak, işlev bağımsız değişkenleri olarak null-ayrılmış tuples ile bazı deneyler yaptım:

$ sayTuple() { 
    IFS= read -r -d $'\0' d1
    IFS= read -r -d $'\0' d2
    echo "sayTuple: -$d1- -$d2-"
}

Notlar: girişi çevreleyen boşluğu işleyen sayTupleboş değerli sonlandırılmış kaydı iki kez okur . geri kayıtları-d $'\0'IFS=echo-

Doğru içeren boş sonlandırılmış girdilerini sonucu göstermektedir \nve \t:

$ printf "%s\0%s\0" "Hello " $' Brave\n\tWorld' | sayTuple 
sayTuple: -Hello - - Brave
        World-

Lütfen yorumlarda iyileştirme önerileri ekleyin, ilginç bir konu.


+ 1 senin fikrin gibi. Bunun yerine, içine rasgele # 's argüman almasını sağlayacak bir döngü koyabiliriz. sayTuple() { arr=() ; while IFS= read -r -d $'\0' arg; do arr+="$arg"; done; echo "sayTuple: ${arr[@]}"; }.
slm

Görünüşe göre bunu yapabilmelisin IFS= read -r -d $'\0' -a argama bunu işe alamadım. Bu while, gereksiz gibi görünen, ancak işe alabileceğim tek desendi.
slm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.