Bash? ile arasındaki fark nedir?

71

Bash << , <<< ve < < arasındaki fark nedir?

    
sordu Searene 27.09.2015 09:42

4 cevap

82

İşte doküman

<< , here-document yapısı olarak bilinir. Programın bitiş metninin ne olacağını bilmesini sağlarsınız ve bu sınırlayıcı ne zaman görülürse, program programa verdiğiniz tüm bilgileri girdi olarak okuyacaktır ve üzerine bir görev gerçekleştirecektir.

İşte demek istediğim:

$ wc << EOF
> one two three
> four five
> EOF
 2  5 24

Bu örnekte, wc programının EOF dizesini beklemesini, ardından beş kelimeyi yazmasını ve girdiyi yaptığımıza işaret etmek için EOF yazmasını söyleriz. Aslında, wc 'yi kendi başına çalıştırarak, sözcükleri yazarak, ardından Ctrl D

tuşlarına basmaya benzer.

Bash olarak, bunlar genellikle /tmp/sh-thd.<random string> biçimindeki temp dosyaları aracılığıyla gerçekleştirilirken, tire içinde anonim borular olarak uygulanırlar. Bu, strace komutuyla izleme sistemi çağrıları ile gözlemlenebilir. % Co_de% 'nın bu yeniden yönlendirmeyi nasıl gerçekleştirdiğini görmek için bash değerini sh ile değiştirin.

$ strace -e open,dup2,pipe,write -f bash -c 'cat <<EOF
> test
> EOF'

Burada dizgi

/bin/sh , <<< olarak bilinir. Metne yazı yazmak yerine, bir programa önceden hazırlanmış bir metin dizesi verirsiniz. Örneğin, here-string gibi bir programla, bu özel durum için çıktı almak için bc yapabiliriz, bc'yi etkileşimli olarak çalıştırmaya gerek yok.

Burada bash dizeleri, genellikle bc <<< 5*4 biçimindeki geçici dosyalar yoluyla, daha sonra bağlantısız olan, böylece geçici olarak bir miktar bellek alanı işgal eden ancak /tmp/sh-thd.<random string> dizin girdisi listesinde görünmeyen geçici dosyalar aracılığıyla uygulanır. etkin bir şekilde anonim dosyalar olarak varolur, bu dosya, kabuk tarafından kendiliğinden dosya tanıtıcısı tarafından başvuruda bulunabilir ve bu dosya tanıtıcısı, komut tarafından devralınır ve sonra /tmp işlevi aracılığıyla dosya tanımlayıcısı 0'a (stdin) çoğaltılır. Bu,

aracılığıyla görülebilir
$ ls -l /proc/self/fd/ <<< "TEST"
total 0
lr-x------ 1 user1 user1 64 Aug 20 13:43 0 -> /tmp/sh-thd.761Lj9 (deleted)
lrwx------ 1 user1 user1 64 Aug 20 13:43 1 -> /dev/pts/4
lrwx------ 1 user1 user1 64 Aug 20 13:43 2 -> /dev/pts/4
lr-x------ 1 user1 user1 64 Aug 20 13:43 3 -> /proc/10068/fd

Ve izleme syscalls (okunabilirlik için kısaltılmış çıktı yoluyla; temp dosyasının fd 3 olarak nasıl yazıldığını, buna yazılan verileri farkettikten sonra, dup2() bayrağı ile fd 4 ve daha sonra bağlantısız olarak yeniden açılır, sonra O_RDONLY fd 0'a, dup2() daha sonra devralınır):

$ strace -f -e open,read,write,dup2,unlink,execve bash -c 'cat <<< "TEST"'
execve("/bin/bash", ["bash", "-c", "cat <<< \"TEST\""], [/* 47 vars */]) = 0
...
strace: Process 10229 attached
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
[pid 10229] write(3, "TEST", 4)         = 4
[pid 10229] write(3, "\n", 1)           = 1
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDONLY) = 4
[pid 10229] unlink("/tmp/sh-thd.uhpSrD") = 0
[pid 10229] dup2(4, 0)                  = 0
[pid 10229] execve("/bin/cat", ["cat"], [/* 47 vars */]) = 0
...
[pid 10229] read(0, "TEST\n", 131072)   = 5
[pid 10229] write(1, "TEST\n", 5TEST
)       = 5
[pid 10229] read(0, "", 131072)         = 0
[pid 10229] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=10229, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

Fikir: potansiyel olarak burada dizeler geçici metin dosyalarını kullanırlar, bu yüzden metin dizeleri POSIX tanımı , satırsonu karakteri ile sonlanan satırlara sahip olmalıdır.

İşlem Değiştirme

tldp.org açıkladığı gibi,

  

Proses ikamesi, bir sürecin (veya süreçlerin) çıktısını besler.   Başka bir sürecin stdin.

Dolayısıyla, bu, bir komutun diğerine stdout aktarılmasıyla benzerdir. cat . Ancak dikkat: bash manpage 'da bunun echo foobar barfoo | wc olarak belirtildiğini görürsünüz. Yani temelde çoklu (!) Komutların çıkışını yönlendirebilirsiniz.

Not: teknik olarak <(list) tek bir şeye atıfta bulunmadığınızı, ancak < < tek ile iki yönlendirme ve < çıkışının yeniden yönlendirilmesini söylediyseniz.

Şimdi ikame işlemini gerçekleştirirsek ne olur?

$ echo <(echo bar)
/dev/fd/63

Gördüğünüz gibi, kabuk çıktı dosyasının bulunduğu geçici dosya tanıtıcısı <( . . .) oluşturur ( Gilles'in cevabı , anonim bir borudır). Bu, /dev/fd/63 dosyasının dosya tanıtıcısını komut olarak girdi olarak yönlendirdiği anlamına gelir.

Öyleyse, çok basit bir örnek, çıktıların iki eko komutundan wc'ye değiştirilmesidir:

$ wc < <(echo bar;echo foo)
      2       2       8

Yani burada kabuk, parantez içinde gerçekleşen tüm çıktılar için bir dosya tanıtıcısı oluşturur ve bunu < girdisi olarak yeniden yönlendiririz. Beklendiği gibi, wc bu akışı iki yankı komutundan alır; , her biri bir kelimeye sahip ve uygun şekilde 2 kelime, 2 satır ve 6 karakter artı iki yeni satır saydık.

Yan Not: Süreç değiştirme bir bashizm olarak adlandırılabilir (POSIX tarafından belirtilmemiş, ancak wc gibi gelişmiş kabuklarda kullanılabilen bir komut veya yapı), ama bash'ın varlığının bash 'sinde ksh man page ve Bu yanıt önerilmektedir. Bununla birlikte, ksh ve tcsh gibi kabuklar, işlem değiştirmeye sahip değildir. Öyleyse, birden fazla komutun çıktısını süreç ikamesi olmadan başka bir komuta yönlendirmek için nasıl gidebiliriz? Gruplama artı borulama!

$ (echo foo;echo bar) | wc
      2       2       8

Etkili olarak yukarıdaki örnekle aynıdır. Ancak, bu, kapsayıcının altında, süreç ikamesinden farklıdır, çünkü, mksh borca ​​bağlı . Öte yandan, işlem yerine koyma komutu, bir komut dosyasını geçici bir dosya tanıtıcısını okur.

Yani, eğer gruplandırma ile borulama yapabilirsek, neden süreç ikamesine ihtiyacımız var? Çünkü bazen boruları kullanamıyoruz. Aşağıdaki örneği ele alalım - iki komutun çıktılarını wc ile karşılaştırarak (iki dosyaya ihtiyaç duyarız ve bu durumda iki dosya tanıtıcısı veriyoruz)

diff <(ls /bin) <(ls /usr/bin)
    
verilen cevap Sergiy Kolodyazhnyy 27.09.2015 09:56
22

< < bir sözdizimi hatası:

$ cat < <
bash: syntax error near unexpected token '<'

< <() , yeniden yönlendirme ( <() ) ile birleştirilen işlem değiştirme ( < ):

Kontrollü bir örnek:

$ wc -l < <(grep ntfs /etc/fstab)
4
$ wc -l <(grep ntfs /etc/fstab)
4 /dev/fd/63

Proses ikamesi ile dosya tanımlayıcısının yolu bir dosya adı gibi kullanılır. Doğrudan bir dosya adı kullanmak istemezseniz (veya kullanamazsanız), işlem değiştirmeyi yeniden yönlendirme ile birleştirirsiniz.

Açık olmak gerekirse, < < işleci yok.

    
verilen cevap muru 27.09.2015 10:05
10

< < bir sözdizimi hatasıdır, büyük olasılıkla command1 < <( command2 ) anlamına gelir, bu da basit bir giriş yönlendirmesidir ve ardından bir işlem ikamesi ile izlenir ve çok benzerdir ancak aşağıdakilere eşdeğer değildir:

command2 | command1

Çalıştırdığınız fark bash 'si command1 ikincisinde bir alt kabukta çalıştırılırken, ilk kabukta geçerli kabukta çalıştırılır. Bu, command1 değerine ayarlanmış değişkenlerin, işlem ikame varyantı ile kaybolacağı anlamına gelir.

    
verilen cevap jlliagre 27.09.2015 10:09
8

< < bir sözdizimi hatası verecektir. Uygun kullanım aşağıdaki gibidir:

Örneklerin yardımıyla açıklanması:

< <() için örnek:

while read line;do
   echo $line
done< <(ls)

Yukarıdaki örnekte while döngüsündeki giriş, satır satır okunabilen ls komutundan ve döngüde echo ed'den gelecektir.

Proses ikamesi için

<() kullanılır. % Co_de% için daha fazla bilgi ve örnek şu bağlantıdan bulunabilir:

Süreç değiştirme ve boru

    
verilen cevap snoop 27.09.2015 10:06

Etiketlerdeki diğer soruları oku