Stdin ve bir dizge nasıl birleştirilir?


108

Stdin'i böyle bir dizeye nasıl birleştirebilirim?

echo "input" | COMMAND "string"

ve Al

inputstring

Yanıtlar:


119

Bir hacky ısırdı ama bu söz (kabul etmek için bir boru kullanmak sordu ne yapacağını en kısa yol olabilir stdoutdan echo "input"kadar stdinbaşka işlem / komutuna:

echo "input" | awk '{print $1"string"}'

Çıktı:

inputstring

Tam olarak hangi görevi başarmaya çalışıyorsun? Daha fazla bağlam, daha iyi bir çözüm konusunda size daha fazla yön verebilir.

Güncelleme - yoruma yanıt:

@NoamRoss

O zaman, istediğiniz şeyi yapmanın daha deyimsel yolu:

echo 'http://dx.doi.org/'"$(pbpaste)"

$(...)Sözdizimi denir komut ikamesi . Kısacası, yeni bir alt kabuğun içerdiği komutları çalıştırır ve stdoutçıktısını $(...), ana kabukta çağrıldığı yere koyar. Yani aslında şunu elde edersiniz:

echo 'http://dx.doi.org/'"rsif.2012.0125"

1
Teşekkürler! Bu harika çalışıyor. Gerçekleştirmeye çalıştığım tam görev, panodan bir dize (bir DOI) alıp başına bir URL eklemek, bu yüzden bunu yapıyorum pbpaste | awk '{print "http://dx.doi.org/"$1}'ve alıyorumhttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross

5
@ sampson-chen, '{print $0"string"}'her şeyi kapmak için kullanırdım .
Roman Newaza

3
Aslında stringher satıra eklenir . Deneyin echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi

55

cat -stdin'den okumak için kullanın $()ve son satır satırını atmak için koyun

echo input | COMMAND "$(cat -)string"

Ancak, neden boruyu bırakıp sol tarafın çıktısını bir komut ikamesinde almıyorsunuz:

COMMAND "$(echo input)string"

1
İşte pratik bir örnek: ~ / other_program / lib -name "* .jar" bul | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / classes"
Ashwin Jayaprakash

2
Bu benim için bash'da çalışıyor, ancak zsh'da "cat: -: Giriş / çıkış hatası" alıyorum. Buna neyin sebep olabileceği hakkında bir fikriniz var mı?
jaymmer - Monica'yı yeniden etkinleştir

"COMMAND", çözümü ve daha karmaşık bir süreç için "yankı girdisi" anlamına gelir. Cattan "-" argümanına sadece başka dosya argümanları varsa gereklidir, aksi takdirde varsayılandır. Yani demek istediğin şuydu: yankı girişi | echo $ (cat) string
Denis Howe

46

Sık sık boru kullanıyorum, bu yüzden bu, stdin'in önekini ve sonekini almanın kolay bir yolu olma eğilimindedir:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix

2
Teşekkürler! Bu aslında çok kullanmanın örneğini serin oluyor pipevecat
Alex Ivasyuv

1
En iyi cevap bu olmalı
Chris Koston

1
Neden sadece: echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix"? Veya daha okunaklı versiyonu:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax

1
@MiniMax Yanıt akışlarla iyi çalıştığından, büyük stdin için çalışacaktır.
anishpatel

1
@anishpatel Benim sürümüm de büyük stdin için çalışacak. Fark yok.
MiniMax

11

Sed ile yapabilirsiniz:

seq 5 | sed '$a\6'
seq 5 | sed '$ s/.*/\0 6/'

Örneğinizde:

echo input | sed 's/.*/\0string/'

9

Bunu başarmanın bazı yolları var, şahsen en iyisinin:

echo input | while read line; do echo $line string; done

Bir diğeri, sed komutunda "$" (satır sonu karakteri) "string" ile değiştirilerek olabilir:

echo input | sed "s/$/ string/g"

Neden ilkini tercih ediyorum? Çünkü bir dizeyi anında stdin ile birleştirir, örneğin aşağıdaki komutla:

(echo input_one ;sleep 5; echo input_two ) | while read line; do echo $line string; done

anında ilk çıktıyı alırsınız:

input_one string

ve 5 saniye sonra diğer yankıyı alırsınız:

input_two string

Öte yandan, "sed" kullanarak önce parantezin tüm içeriğini gerçekleştirir ve sonra onu "sed" e verir, dolayısıyla komut

(echo input_one ;sleep 5; echo input_two ) | sed "s/$/ string/g"

her iki satırı da çıkaracak

input_one string
input_two string

5 saniye sonra.

Bu, tamamlanması uzun süren işlev çağrıları yaptığınız ve işlevin çıktısı hakkında sürekli olarak güncellenmek istediğiniz durumlarda çok yararlı olabilir.


Aslında, sed seçeneği de her girdi satırını anında işler.
tomekwi

Tek satırlık bir girdi için en basit çözüm yankı girdisidir | (v; echo $ {v} dizesini okuyun) Bu saf kabuktur, dolayısıyla sed gibi ekstra bir işlem gerektirmez.
Denis Howe

7

Bunun birkaç yıl geciktiğini biliyorum, ancak bunu xargs -J seçeneğiyle başarabilirsiniz:

echo "input" | xargs -J "%" echo "%" "string"

O zamandan beri Ve olduğunu xargs, aynı anda bir dosyanın birden fazla hat üzerinde yapabilirsiniz. Dosya 'adları' üç satıra sahipse, örneğin:

Adam
Bob
Charlie

Yapabilirsin:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"

1
-JStandart / yaygın görünmemesi dışında havalı görünüyor. Linux'ta (nerede xargsparçası GNU findutils) şu hatayı alıyorum: xargs: invalid option -- 'J'Bu hangi sistemde?
arielf

3
-JMac sürümü içindir. Linux -Iiçin aynı işlevi yerine getirir.
user2635263

1
Teşekkürler! çok kullanışlı. Lütfen Linux'ta bu basitleştirilmiş sürümün de aynı şekilde çalıştığına dikkat edin: cat names | xargs -I% echo "I like % because he is nice"IOW: buna gerek yok -n 1( zaten her girdi satırında bir kez xargsçağrılar echo, çünkü -Iima eder -L1) Ayrıca, tüm ayrı arg alıntılar gereksiz görünmektedir.
arielf

3

Gönderdiğiniz komut "girdi" dizesini alır ve onu COMMAND'ın stdin akışı olarak kullanır, bu da COMMAND önce stdin içeriğini yazdırıp sonra komut satırı argümanlarını yazdırmadıkça aradığınız sonuçları üretmez.

Görünüşe göre, yapmak istediğin şey komut değiştirmeye daha yakın.

http://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html#Command-Substitution

Komut ikamesi ile aşağıdaki gibi bir komut satırına sahip olabilirsiniz:

echo input `COMMAND "string"`

Bu, önce COMMAND'i girdi olarak "string" ile değerlendirecek ve sonra bu komutların yürütülmesinin sonuçlarını bir satıra genişleterek '' 'karakterleri arasındakileri değiştirecektir.


ve tabii ki @NaomRoss, Bourne kabuğunu kullanmanız gerekmediği veya başka çılgın "taşınabilirlik" yetkilerine sahip olmadığınız sürece echo input $(COMMAND "string"), ters işaretler yerine modern komut ikamesini kullanacaksınız . Hepinize iyi şanslar.
shellter

1

kedi benim seçimim olacak: ls | cat - <(echo new line)


sed, yukarı akış borusunun hiçbir çıktısı yoksa çalışmayan hat tabanlı bir komuttur.
clarkttfu

0

Ayrıca çalışır:

seq -w 0 100 | xargs -I {} echo "string "{}

Aşağıdaki gibi dizeler oluşturacaktır:

string 000
string 001
string 002
string 003
string 004

...

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.