Bagaimana cara menggabungkan stdin dan string?

108

Bagaimana cara menggabungkan stdin ke string, seperti ini?

echo "input" | COMMAND "string"

dan dapatkan

inputstring
Noam Ross
sumber

Jawaban:

119

Agak hacky, tetapi ini mungkin cara terpendek untuk melakukan apa yang Anda tanyakan dalam pertanyaan (gunakan pipa untuk menerima stdoutdari echo "input"sebagai stdinke proses / perintah lain:

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

Keluaran:

inputstring

Tugas apa yang sebenarnya Anda coba selesaikan? Lebih banyak konteks dapat memberi Anda lebih banyak arahan tentang solusi yang lebih baik.

Perbarui - menanggapi komentar:

@Bayu_joo

Cara yang lebih idiomatis untuk melakukan apa yang Anda inginkan adalah:

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

The $(...)sintaks disebut perintah substitusi . Singkatnya, ia mengeksekusi perintah yang diapit dalam subkulit baru, dan mengganti stdoutoutputnya ke tempat $(...)dipanggil di shell induk. Jadi Anda akan mendapatkan, pada dasarnya:

echo 'http://dx.doi.org/'"rsif.2012.0125"
sampson-chen
sumber
1
Terima kasih! Ini bekerja dengan baik. Tugas sebenarnya yang saya coba selesaikan adalah mengambil string dari clipboard (DOI) dan menambahkan URL ke dalamnya, jadi dengan ini saya lakukan pbpaste | awk '{print "http://dx.doi.org/"$1}'dan dapatkanhttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross
5
@ sampson-chen, saya akan gunakan '{print $0"string"}'untuk mengambil semuanya.
Roman Newaza
3
Itu sebenarnya ditambahkan stringke setiap baris. Coba echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi
55

gunakan cat -untuk membaca dari stdin, dan masukkan $()ke dalam untuk membuang baris baru yang tertinggal

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

Namun mengapa Anda tidak menjatuhkan pipa dan mengambil output dari sisi kiri dalam substitusi perintah:

COMMAND "$(echo input)string"
glenn jackman
sumber
1
Berikut adalah contoh praktisnya: find ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | echo "$ (kucing -) ~ / java_app / kelas"
Ashwin Jayaprakash
2
Ini berfungsi untuk saya di bash, tetapi di zsh saya mendapatkan "cat: -: Kesalahan input / output". Tahu apa yang bisa menyebabkan ini?
jaymmer
"COMMAND" adalah singkatan dari solusi dan "masukan gema" untuk beberapa proses yang lebih rumit. Arg "-" ke cat hanya diperlukan jika ada file lain args, jika tidak maka defaultnya. Jadi yang Anda maksud adalah: input gema | echo $ (cat) string
Denis Howe
46

Saya sering menggunakan pipa, jadi ini cenderung menjadi cara mudah untuk memberi awalan dan akhiran stdin:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix
rupert160
sumber
2
Terima kasih! Itu sebenarnya contoh penggunaan yang sangat keren pipedancat
Alex Ivasyuv
1
Ini harus menjadi jawaban terbaik
Chris Koston
1
Mengapa tidak hanya echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix":? Atau, versi yang lebih mudah dibaca:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax
1
@MiniMax Karena jawabannya berfungsi baik dengan aliran, ini akan berfungsi untuk stdin besar.
anishpatel
1
@anishpatel Versi saya akan berfungsi untuk stdin besar juga. Tidak ada perbedaan.
MiniMax
11

Anda dapat melakukannya dengan sed:

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

Dalam contoh Anda:

echo input | sed 's/.*/\0string/'
Vytenis Bivainis
sumber
9

Ada beberapa cara untuk melakukannya, menurut saya yang terbaik adalah:

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

Lain dapat dengan mengganti "$" (karakter akhir baris) dengan "string" dalam perintah sed:

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

Mengapa saya lebih memilih yang pertama? Karena itu menggabungkan string ke stdin secara instan, misalnya dengan perintah berikut:

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

Anda segera mendapatkan hasil pertama:

input_one string

dan kemudian setelah 5 detik Anda mendapatkan gema lainnya:

input_two string

Di sisi lain, menggunakan "sed" terlebih dahulu melakukan semua konten tanda kurung dan kemudian memberikannya ke "sed", jadi perintah

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

akan menampilkan kedua baris

input_one string
input_two string

setelah 5 detik.

Ini bisa sangat berguna jika Anda melakukan panggilan ke fungsi yang membutuhkan waktu lama untuk menyelesaikannya dan ingin terus diperbarui tentang keluaran fungsi.

Simone
sumber
Sebenarnya, opsi sed juga memproses setiap baris input secara instan.
tomekwi
Untuk satu baris masukan, solusi paling sederhana adalah masukan gema | (baca v; echo $ {v} string) Itu adalah shell murni sehingga tidak membutuhkan proses tambahan seperti sed.
Denis Howe
7

Saya tahu ini terlambat beberapa tahun, tetapi Anda dapat melakukannya dengan opsi xargs -J:

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

Dan karena ini adalah xargs, Anda dapat melakukan ini pada beberapa baris file sekaligus. Jika file 'names' memiliki tiga baris, seperti:

Adam
Bob
Charlie

Anda bisa melakukan:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"
pengguna2635263
sumber
1
Tampak keren kecuali -Jsepertinya tidak standar / umum. Di Linux (di mana xargsbagiannya GNU findutils) saya mendapatkan error: Di xargs: invalid option -- 'J'sistem mana ini?
arielf
3
-Jadalah untuk versi Mac. Untuk Linux -Imelakukan fungsi yang sama.
pengguna2635263
1
Terima kasih! sangat berguna. Harap dicatat bahwa di Linux, versi yang disederhanakan ini bekerja dengan baik: cat names | xargs -I% echo "I like % because he is nice"IOW: tidak perlu untuk -n 1( xargspanggilan echosekali per baris masukan, karena -Imenyiratkan -L1) Juga, semua kutipan arg terpisah, tampaknya berlebihan.
arielf
3

Perintah yang Anda kirimkan akan mengambil string "input" menggunakannya sebagai aliran stdin COMMAND, yang tidak akan menghasilkan hasil yang Anda cari kecuali COMMAND pertama kali mencetak konten stdin dan kemudian mencetak argumen baris perintahnya.

Sepertinya yang ingin Anda lakukan lebih dekat dengan penggantian perintah.

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

Dengan substitusi perintah Anda dapat memiliki baris perintah seperti ini:

echo input `COMMAND "string"`

Ini pertama-tama akan mengevaluasi COMMAND dengan "string" sebagai input, dan kemudian memperluas hasil eksekusi perintah tersebut ke dalam baris, menggantikan apa yang ada di antara karakter '`'.

Max DeLiso
sumber
dan tentu saja @NaomRoss, kecuali jika Anda diharuskan menggunakan Bourne shell atau memiliki mandat "portabilitas" gila lainnya, Anda akan menggunakan substitusi perintah modern seperti echo input $(COMMAND "string"), daripada backticks. Semoga beruntung untuk semuanya.
shellter
1

kucing akan menjadi pilihan saya: ls | cat - <(echo new line)

clarkttfu
sumber
sed adalah perintah berbasis baris yang tidak berfungsi jika pipa hulu tidak memiliki keluaran ..
clarkttfu
0

Juga bekerja:

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

Akan menghasilkan string seperti:

string 000
string 001
string 002
string 003
string 004

...

cy8g3n
sumber