Pipe memberikan variabel

19

Untuk kesederhanaan, saya ingin melakukan:

echo cart | assign spo;
echo $spo  

Output: kereta

Apakah assignaplikasi semacam itu ada?

Saya menyadari semua cara untuk melakukan ini menggunakan subtitusi.

MageProspero
sumber
Mengapa Anda ingin melakukan ini tanpa substitusi?
Thanatos
Saya suka aliran notasi Polandia terbalik saat menulis dengan pipa saja. Saya coding lebih cepat dan kualitas kode / kecepatan tidak begitu penting. Juga saya tidak ketika merantai itu akan lebih mudah untuk mengomentari bagian dari rantai dan menggemakan output saat ini daripada menghapus kutu dll.
MageProspero
Jika Anda khawatir tentang kemudahan debug, pertimbangkan untuk menempatkan perintah backticks pada serangkaian baris terpisah. A=$( some | command | here )dengan masing-masing some |, command |dan herepada baris sendiri.
roaima

Jawaban:

11
echo cart | { IFS= read -r spo; printf '%s\n' "$spo"; }

Akan bekerja (menyimpan output echotanpa karakter baris baru ke dalam spovariabel) selama echooutput hanya satu baris.

Anda selalu bisa melakukan:

assign() {
  eval "$1=\$(cat; echo .); $1=\${$1%.}"
}
assign spo < <(echo cart)

Solusi berikut akan berfungsi dalam bashskrip, tetapi tidak pada bashprompt:

shopt -s lastpipe
echo cat | assign spo

Atau:

shopt -s lastpipe
whatever | IFS= read -rd '' spo

Untuk menyimpan output whateverhingga karakter NUL pertama ( bashvariabel tetap tidak dapat menyimpan karakter NUL) di $spo.

Atau:

shopt -s lastpipe
whatever | readarray -t spo

untuk menyimpan output whateverdalam $spo array (satu baris per elemen array).

Stéphane Chazelas
sumber
1
tidakkah seharusnya ada jarak di antara IFS=dan read?
caesarsol
Semua salam pipa terakhir. Juga set catatan samping + m (ermmm atau -m) diperlukan dari baris perintah dia karena pipa terakhir tidak bekerja dengan kontrol pekerjaan aktif.
MageProspero
17

Anda dapat melakukan sesuatu seperti ini, jika Anda menggunakan bash:

echo cart | while read spo; do echo $spo; done

Sayangnya, variabel "spo" tidak akan ada di luar loop while-do-done. Jika Anda bisa menyelesaikan apa yang Anda inginkan di dalam while-loop, itu akan berhasil.

Anda benar-benar dapat melakukan hampir apa yang Anda tulis di atas di ATT ksh (bukan di pdksh atau mksh) atau di zsh yang menakjubkan:

% echo cart | read spo
% echo $spo
cart

Jadi, solusi lain adalah menggunakan ksh atau zsh.

Bruce Ediger
sumber
1
Anda dapat menggunakan proses-proses dalam Korn Shell (mis. mksh): echo cart |& while read -p spo; do echo $spo; done(Sebenarnya lebih baik digunakan while IFS= read -p -r spo; do…)
mirabilos
2

Jika saya memahami masalah ini dengan benar, Anda ingin mengirim stdout ke variabel. Setidaknya itulah yang saya cari dan berakhir di sini. Jadi bagi mereka yang berbagi nasib saya:

spa=$(echo cart)

Ditugaskan cartke variabel $spa.

zack-vii
sumber
2
Itulah yang mereka sebut substitusi, yang ingin dihindari OP.
Dmitry Grigoryev
Ini berguna bagi saya, saya hanya perlu menugaskannya ke variabel, saya tidak peduli bagaimana sampai di sana!
Chris Marisic
1

Jika Anda hanya ingin menampilkan penggunaan aliran pipa saat ini cat.

echo cart | cat 

Jika Anda ingin melanjutkan rantai perintah Anda, coba gunakan teeperintah untuk mengulang output.

echo cart | tee /dev/tty | xargs ls

Anda bisa menggunakan alias untuk mempersingkat perintah.

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
BillThor
sumber
Mengapa Anda ingin menyalurkan output ke dataran cat?
roaima
1
@roaima Beberapa perintah mengenali bahwa mereka berjalan pada terminal dan berperilaku berbeda dari jika mereka mengeluarkan ke pipa. Khususnya mereka dapat memotong garis ke lebar layar saat ini. Untuk sebagian besar perintah, perintah kucing berlebihan.
BillThor
Ah ok, saya mengerti sekarang apa yang Anda coba gambarkan. The echo | catmembangun melemparkan saya.
roaima
1

Inilah solusi saya untuk masalah ini.

# assign will take last line of stdout and create an environment variable from it
# notes: a.) we avoid functions so that we can write to the current environment
#        b.) aliases don't take arguments, but we write this so that the "argument" appears
#            behind the alias, making it appear as though it is taking one, which in turn
#            becomes an actual argument into the temporary script T2.
# example: echo hello world | assign x && echo %x outputs "hello world"
alias assign="tail -1|tee _T1>/dev/null&&printf \"export \\\$1=\$(cat _T1)\nrm _T*\">_T2&&. _T2"
Brian Kramer
sumber