Bir dosyayı bekleyen programa metin iletme


29

Yığın Taşması hakkında sorduğum bir soru ile ilgili: wsadmin.sh dosyasına birden çok kod satırı geçmek? .

Bir dizge olarak, bir komuta beslemem gereken birkaç girdi satırına sahibim. Bununla birlikte, komut yalnızca girdiyle dolu bir dosyayı kabul eder.

Satırları, diske hiç yazılmayan ve doğrudan programa besleyen geçici bir dosyada veya boruda depolayabilmemin bir yolu var mı?

Boruyu almaya, girişi beslemeye, boruyu komuta geçirmeye ve borudan kurtulmaya nasıl giderim?


2
Kullanmakta olduğunuz komutun bir örneğini ve nasıl çağrılması gerektiğini ekleyebilir misiniz?
Atılım

2
Bu, programın stdin kabul etmediği anlamına mı geliyor?
Léo Lam,

Yukarıdaki iki yorumcuya katılıyorum. Programın özelliklerini bilmeden çalışabilecek bir şey önermek imkansızdır.
Larssend

Yanıtlar:


26

Başka bir çözüm de Bash'de İşlem Değişimini kullanmaktır . Sisteminizde boru adı varsa, bu özelliği kullanabilirsiniz.

Bu gibi kullanılır:

program_expecting_a_file <(list)

Burada listbir kabuk komutları dizisidir (aslında boru hatları; tüm detaylar burada ). listyürütülecek ve çıkışı boruya bağlanacaktır. Borunun adı daha sonra programınıza iletilir.

NOT:< ve arasında boşluk bırakılamaz (.

(Diğer değişiklik >(list)de beklediğiniz gibi çalışır.)

Özel bir durumda, kullanabilirsiniz

program_expecting_a_file <(echo "$your_strings")

Bununla birlikte @ meuh'un çözümünü daha şık bulabilirsin.

Güncelleme: Çok sayıda kullanım örneği Advanced Bash Scripting Guide'da bulunabilir .


Diğer ikisi, en önemsiz vakalarda bile işe yaramadı. Seninki şu ana kadar fırlattığım testleri geçti. Şimdilik seninkileri değiştirdim. İhtiyacım olan her şeyi yaparsa geri dönüp bunu kabul edilmiş olarak işaretleyeceğim.
ArtOfWarfare

Seninkiler mükemmel çalışıyor. İsterseniz, StackOverflow'ta ilgili soruya ekleyebilir ve ben de orada kabul edebilirim. stackoverflow.com/questions/31374202/…
ArtOfWarfare

Merhaba @ ArtOfWarfare, yardımcı olmaktan mutluluk duyuyorum. Aynı çözüm önerisiyle zaten orada bir yorum yapıldı, bu yüzden oraya bir cevap göndermem doğru olmaz.
Edward

Çözümünü ondan önce gönderdin. Her neyse, ondan yorumunu bir cevap olarak değiştirmesini istedim, böylece kabul edebilirim. İkiniz de bu soruya 24 saat içinde cevap yazmazsanız, cevabı kendim gönderirim, böylece kabul edebilirim (cevabımın ne olduğunu bulduğumda sorularımı cevapsız olarak bırakmayı sevmiyorum. Gelecekteki okuyucular / sorunun potansiyel cevaplayıcıları için sadece kötü davranışlar.)
ArtOfWarfare

Merhaba @ArtOfWarfare, önerdiğiniz şeyle kesinlikle iyiyim!
Edward

14

Burada bir bash kullanabilirsiniz . Örneğin,

$ cat -n <<<'a
> b'
 1  a
 2  b

Bir bash değişkeninde bir şey varsa onu da enterpolasyon yapabilirsiniz: örn <<<"path is $PATH".


Komutunuz dosya isminde ısrar ederse, onu verebilirsiniz /dev/stdin. Örneğin:

$ sed -f /dev/stdin <<<'s/a/b/'

çıktı üretir: s/b/b/.


Komutun girişi kabul edip etmediği sorusundan belli değil stdinve eğer değilse, bu işe yaramayacak. Umarım OP netleşir.
David Z,

1
:( - Bu süper umut verici görünüyordu, ama denediğimde hata mesajını aldım"-f" option must be followed by a file name.
ArtOfWarfare 13:15

Bir burada-doktor stdin içindir. Komutunuz kesinlikle gerekiyorsa -fve bir dosya adı varsa, o zaman dosya adını sağlayın /dev/stdin. Düzenlemeye bak.
meuh

Düzenlemelerden sonra kesinlikle uygun bir seçenek olduğunu düşünüyorum!
Edward

/dev/stdinÖneri için +1 . Aramaya çalıştığım program sadece bir dosya /dev/stdinadını kabul ediyor, bu yüzden heredoc ile birleştirdim .
Huw Walters,

7

Senaryodaki ne olduğuna bağlı olarak, olabilir (eksi) açılımı - özel dosya adı kullanabilecektir Stdin

$ mycmd -
Line 1
Line 2
^D

Sizin için işe yarayabilecek başka bir yöntem ise /dev/fd/0yine stdin anlamına gelen dosyayı açmaktır .

Üçüncü bir seçenek FIFO (İlk Giren İlk Çıkar) oluşturmak için olabilir . Bu bir dosya gibidir, ancak bunun iki ucu vardır - bir uca yazıp diğerinden okursunuz.

-- Process 1 --                  -- Process 2 --
$ mkfifo foo
$ cat foo
<waits>                          $ echo hello > foo
hello                            $
$ rm foo

3
-Bu şekilde yorumlamak için programın yazılması gerektiğine dikkat etmek faydalı olabilir - bu, kabuğun veya işletim sisteminin bir özelliği değildir. Tabii ki çoğu standart Linux programı bildiğim kadarıyla bu sözleşmeyi takip ediyor.
David Z,

1
Hayır! Bu program için çalışmıyor. Etkileşimli bir mod var, ancak başka bir programdan bu programa uygulamak için komutları iletmek istiyorum ve bu olanı tavşan deliğine girmek istemiyorum expect.
ArtOfWarfare

@ArtOfWarfare Sadece işe yarayabilecek üçüncü bir seçenek ekledim.
Majenko,

Güzel cevap! İkinci ve üçüncü seçenekler temel olarak <()çözüme benzer, ancak daha açık - ki bu çok faydalı olabilir!
Edward

3

Çözüme benzer mycmd -, ancak -özellikle işlenmeyen programlar için bile başka bir seçenek var :

$ mycmd /dev/stdin
Line 1
Line 2
^D

/dev/stdin İşletim sistemi ile ilgili görünüyor ve benim için Debian GNU / Linux'ta çalışıyor, fakat başka nerede de çalışacağından emin değilim.


1
Bu işe yarayabilir gibi görünüyor, ama nedir ^D?
ArtOfWarfare

^DCtrl-D'ye basmak için ortak bir notasyondur. ^ D burada "giriş akışının sonu" ifadesine sahiptir. Muhtemelen Ctrl-Z'ye basmak için sırasıyla Ctrl-C'ye basmak için ^Cya ^Zda ayakta durmak daha sık görülür .
Axel Beckert

1
İşe yarayacak gibi gözüküyor, ama nasıl programatik olarak eşyaları içine koyar /dev/stdinve sonra kapatırım?
ArtOfWarfare

1
Sadece bir komutu bu komuta sokun ve çalışması gerekir, yani cat content | mycmd /dev/stdin. Sadece catburadakinden farklı komutları hayal edin .
Axel Beckert
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.