Saya mencoba untuk mendapatkan bash untuk memproses data dari stdin yang akan disalurkan ke dalam, tapi tidak berhasil. Yang saya maksud adalah tidak ada pekerjaan berikut:
echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=
echo "hello world" | read test; echo test=$test
test=
echo "hello world" | test=`cat`; echo test=$test
test=
di mana saya ingin output untuk menjadi test=hello world
. I've mencoba menempatkan "," tanda kutip "$test"
yang doesn't bekerja dengan baik.
Gunakan
IFS= read var << EOF
$(foo)
EOF
Anda bisa trik membaca
dalam menerima dari pipa seperti ini:
echo "hello world" | { read test; echo test=$test; }
atau bahkan menulis fungsi seperti ini:
read_from_pipe() { read "$@" <&0; }
Tapi ada's tidak ada titik - variabel tugas tidak dapat berlangsung! Pipa dapat menelurkan sebuah subkulit, di mana lingkungan yang diwariskan oleh value, bukan by reference. Ini adalah mengapa baca
doesn't repot-repot dengan masukan dari pipa - it's tidak terdefinisi.
FYI, http://www.etalabs.net/sh_tricks.html bagus koleksi cruft diperlukan untuk melawan keanehan dan inkompatibilitas bourne, sh.
jika anda ingin membaca di banyak data dan bekerja pada setiap baris secara terpisah, anda bisa menggunakan sesuatu seperti ini:
cat myFile | while read x ; do echo $x ; done
jika anda ingin membagi garis menjadi beberapa kata, anda dapat menggunakan beberapa variabel pada x seperti ini:
cat myFile | while read x y ; do echo $y $x ; done
atau:
while read x y ; do echo $y $x ; done < myFile
Tapi segera setelah anda mulai untuk ingin melakukan sesuatu yang benar-benar pintar dengan hal semacam ini, anda're baik akan untuk beberapa bahasa script seperti perl di mana anda dapat mencoba sesuatu seperti ini:
perl -ane 'print "$F[0]\n"' < myFile
Ada's cukup kurva belajar yang curam dengan perl (atau saya kira salah satu dari bahasa-bahasa ini) tapi anda'll menemukan ini jauh lebih mudah dalam jangka panjang jika anda ingin melakukan apa-apa tapi sederhana dari script. I'd merekomendasikan Perl Masak dan, tentu saja, Bahasa Pemrograman Perl oleh Larry Wall et al.
Ini adalah pilihan lain
$ read test < <(echo hello world)
$ echo $test
hello world
baca
tidak't baca dari sebuah pipa (atau mungkin hasilnya hilang karena pipa menciptakan subkulit). Namun, anda dapat menggunakan berikut string di Bash:
$ read a b c <<< $(echo 1 2 3)
$ echo $a $b $c
1 2 3
Tapi melihat @chepner's jawaban untuk informasi tentang lastpipe
.
I'm tidak ahli dalam Bash, tapi aku bertanya-tanya mengapa ini tidak't telah diusulkan:
stdin=$(cat)
echo "$stdin"
Satu-liner bukti bahwa ia bekerja untuk saya:
$ fortune | eval 'stdin=$(cat); echo "$stdin"'
bash
4.2 memperkenalkan lastpipe
pilihan, yang memungkinkan kode anda untuk bekerja seperti yang tertulis, dengan mengeksekusi perintah terakhir dalam pipa pada shell saat ini, daripada subkulit.
shopt -s lastpipe
echo "hello world" | read test; echo test=$test
Upaya pertama adalah cukup dekat. Variasi ini harus bekerja:
echo "hello world" | { test=$(< /dev/stdin); echo "test=$test"; };
dan output adalah:
tes=halo dunia
Anda perlu kawat gigi setelah pipa untuk melampirkan tugas untuk menguji dan echo.
Tanpa kawat gigi, tugas untuk tes (setelah pipa) adalah dalam satu shell, dan echo "test=$test" di tempat terpisah shell yang doesn't tahu tentang penugasan itu. Yang's mengapa anda mendapatkan "test=" dalam output bukan "test=halo dunia".
Karena aku jatuh untuk itu, saya ingin menjatuhkan catatan. Saya menemukan thread ini, karena saya harus menulis ulang tua sh script untuk menjadi POSIX compatible. Ini pada dasarnya berarti untuk menghindari pipa/subkulit masalah yang diperkenalkan oleh POSIX dengan menulis ulang kode seperti ini:
some_command | read a b c
ke:
read a b c << EOF
$(some_command)
EOF
Dan kode seperti ini:
some_command |
while read a b c; do
# something
done
ke:
while read a b c; do
# something
done << EOF
$(some_command)
EOF
Tetapi yang terakhir tidak berperilaku yang sama pada masukan kosong. Dengan notasi loop sementara tidak dimasukkan di masukan kosong, tapi di POSIX notasi itu! Saya pikir itu's karena newline sebelum EOF, yang tidak dapat dihilangkan. POSIX kode yang berperilaku lebih seperti notasi terlihat seperti ini:
while read a b c; do
case $a in ("") break; esac
# something
done << EOF
$(some_command)
EOF
Dalam kebanyakan kasus ini harus cukup baik. Tapi sayangnya ini masih berperilaku tidak persis seperti notasi jika some_command cetak baris kosong. Di old notasi sementara tubuh dieksekusi dan di POSIX notasi kami istirahat di depan tubuh.
Suatu pendekatan untuk memperbaiki kesalahan ini mungkin terlihat seperti ini:
while read a b c; do
case $a in ("something_guaranteed_not_to_be_printed_by_some_command") break; esac
# something
done << EOF
$(some_command)
echo "something_guaranteed_not_to_be_printed_by_some_command"
EOF
Kode berikut:
echo "hello world" | ( test=($(< /dev/stdin)); echo test=$test )
akan bekerja juga, tapi itu akan membuka lagi baru sub-shell setelah pipa, di mana
echo "hello world" | { test=($(< /dev/stdin)); echo test=$test; }
won't.
Aku harus menonaktifkan kontrol pekerjaan untuk membuat penggunaan chepnars' metode (saya menjalankan perintah ini dari terminal):
set +m;shopt -s lastpipe
echo "hello world" | read test; echo test=$test
echo "hello world" | test="$(</dev/stdin)"; echo test=$test
lastpipe
Jika ditetapkan, dan pekerjaan kontrol tidak aktif, shell menjalankan perintah terakhir pipa tidak dijalankan di latar belakang saat ini shell lingkungan.
Catatan: kontrol pekerjaan dimatikan secara default di non-interaktif shell dan dengan demikian anda don't perlu set +m
dalam naskah.
Saya pikir anda mencoba untuk menulis sebuah skrip shell yang bisa mengambil input dari stdin. tapi saat anda mencoba untuk melakukannya inline, anda tersesat mencoba untuk membuat bahwa tes= variabel. Saya pikir itu tidak masuk akal untuk melakukannya inline, dan yang's mengapa hal itu tidak bekerja seperti yang anda harapkan.
Saya mencoba untuk mengurangi
$( ... | head -n $X | tail -n 1 )
untuk mendapatkan baris tertentu dari berbagai input. jadi saya bisa mengetik...
cat program_file.c | line 34
jadi saya perlu kecil program shell dapat baca dari stdin. seperti yang anda lakukan.
22:14 ~ $ cat ~/bin/line
#!/bin/sh
if [ $# -ne 1 ]; then echo enter a line number to display; exit; fi
cat | head -n $1 | tail -n 1
22:16 ~ $
di sana anda pergi.
Pintar script yang dapat membaca data dari PIPA dan argumen baris perintah:
#!/bin/bash
if [[ -p /proc/self/fd/0 ]]
then
PIPE=$(cat -)
echo "PIPE=$PIPE"
fi
echo "ARGS=$@"
Output:
$ bash test arg1 arg2
ARGS=arg1 arg2
$ echo pipe_data1 | bash test arg1 arg2
PIPE=pipe_data1
ARGS=arg1 arg2
Penjelasan: Ketika sebuah script menerima data melalui pipa, maka stdin /proc/self/fd/0 akan symlink ke pipa.
/proc/self/fd/0 -> pipe:[155938]
Jika tidak, hal itu akan mengarah ke terminal saat ini:
/proc/self/fd/0 -> /dev/pts/5
Bash jika -p
pilihan dapat memeriksa itu adalah pipa atau tidak.
kucing
membaca dari stdin
.
Jika kita menggunakan kucing
ketika tidak ada stdin
, itu akan menunggu selamanya, itu sebabnya kami menempatkan itu di dalam jika
kondisi.