Dalam skrip shell ...
Bagaimana cara menangkap stdin ke variabel tanpa menghapus baris baru yang tertinggal?
Saat ini saya sudah mencoba:
var=`cat`
var=`tee`
var=$(tee)
Dalam semua kasus $var
tidak akan memiliki baris baru dari aliran input. Terima kasih.
JUGA: Jika tidak ada baris baru di input, maka solusinya tidak harus menambahkan satu .
DIPERBARUI DALAM CAHAYA DARI JAWABAN YANG DITERIMA:
Solusi terakhir yang saya gunakan dalam kode saya adalah sebagai berikut:
function filter() {
#do lots of sed operations
#see https://github.com/gistya/expandr for full code
}
GIT_INPUT=`cat; echo x`
FILTERED_OUTPUT=$(printf '%s' "$GIT_INPUT" | filter)
FILTERED_OUTPUT=${FILTERED_OUTPUT%x}
printf '%s' "$FILTERED_OUTPUT"
Jika Anda ingin melihat kode lengkapnya, silakan lihat halaman github untuk expandr , sebuah skrip shell filter-ekspansi git kata kunci open source yang saya kembangkan untuk tujuan keamanan informasi. Menurut aturan yang diatur dalam file .gitattributes (yang bisa spesifik cabang) dan git config , git mem -pipe setiap file melalui skrip shell Expandr.sh setiap kali mengecek masuk atau keluar dari repositori. (Itulah sebabnya sangat penting untuk menjaga jalur baru yang tertinggal, atau kekurangannya.) Ini memungkinkan Anda membersihkan informasi sensitif, dan bertukar dalam set nilai lingkungan yang berbeda untuk pengujian, pementasan, dan cabang langsung.
filter
Dibutuhkanstdin
- itu berjalansed
. Anda menangkapstdin
di$GIT_INPUT
kemudian mencetak yang kembali kestdout
atas pipa untukfilter
dan menangkap nyastdout
di$FILTERED_OUTPUT
kemudian mencetaknya kembali kestdout
. Semua 4 baris di bagian bawah contoh di atas bisa diganti dengan hanya ini:filter
. Jangan tersinggung di sini, hanya saja ... Anda bekerja terlalu keras. Anda tidak perlu variabel shell sebagian besar waktu - hanya mengarahkan input ke tempat yang tepat dan meneruskannya.filter
, maka itu akan menambahkan karakter baris baru ke ujung setiap aliran input yang awalnya tidak berakhir di baris baru. Sebenarnya saya awalnya hanya melakukanfilter
tetapi mengalami masalah yang menyebabkan saya untuk solusi ini karena tidak "selalu menambahkan baris baru" atau "selalu strip baris baru" adalah solusi yang dapat diterima.sed
mungkin akan melakukan baris baru ekstra - tetapi Anda harus mengatasinyafilter
dengan yang lain. Dan semua fungsi yang Anda miliki pada dasarnya melakukan hal yang sama - ased s///
. Anda menggunakan shell untuk mem-pipe data yang telah disimpannya di memorinyased
sehinggased
dapat menggantikan data itu dengan data lain yang telah disimpan shell dalam memorinya sehinggased
dapat menyalurkannya kembali ke shell. Kenapa tidak adil[ "$var" = "$condition" ] && var=new_value
? Saya juga tidak mendapatkan array - apakah Anda menyimpan nama array di[0]
kemudian gunakansed
untuk menggantikannya dengan nilai[1]
? Mungkin mengobrol?filter
? Ini berfungsi dengan baik apa adanya. Mengenai cara kerja kode di tautan saya dan mengapa saya mengaturnya seperti yang saya lakukan, ya, mari kita bicarakan di ruang obrolan.Jawaban:
Baris baru yang tertinggal dilucuti sebelum nilai disimpan dalam variabel. Anda mungkin ingin melakukan sesuatu seperti:
dan gunakan
${var%x}
sebagai gantinya$var
. Contohnya:Perhatikan bahwa ini menyelesaikan masalah baris baru, tetapi bukan byte nol (jika input standar bukan teks), karena menurut substitusi perintah POSIX :
Tetapi implementasi shell dapat mempertahankan byte nol.
sumber
Anda dapat menggunakan
read
bawaan untuk melakukan ini:Agar skrip membaca STDIN, itu hanya akan:
Saya tidak yakin apa kerang ini akan bekerja. Tapi berfungsi dengan baik di bash dan zsh.
sumber
-d
subtitusi proses (<(...)
) tidak portabel; kode ini tidak akan berfungsidash
, misalnya.-d
, itu sebabnya saya menempatkan disclaimer di bagian bawah. OP tidak menentukan shell.dash
. Anda hanya menggunakan<<HEREDOC\n$(gen input)\nHEREDOC\n
- indash
- yang menggunakan pipa untuk heredocs dengan cara yang sama dengan shell lain yang menggunakannya untuk proses substitusi - tidak ada bedanya. Theread -d
hal hanya menentukan pembatas - Anda dapat melakukan selusin cara yang sama - hanya menjadi yakin tentang hal itu. Meskipun Anda perlu ekorgen input
.IFS=''
mungkin tidak perlu. Ini dimaksudkan agarread
tidak membuat ruang kosong. Tetapi ketika sedang membaca ke dalam satu variabel, itu tidak memiliki efek (yang saya ingat). Tapi saya merasa lebih aman meninggalkannya pada :-)Anda dapat melakukannya seperti:
Apa pun yang Anda lakukan
$var
menghilang begitu Anda keluar dari{ current shell ; }
pengelompokan itu. Tetapi bisa juga berfungsi seperti:sumber
$var
dalam{ ... }
pengelompokan, tidak selalu mungkin. Sebagai contoh jika perintah ini dijalankan di dalam loop dan seseorang perlu di$var
luar loop.{}
kawat gigi .Ini adalah benar - dan secara eksplisit dicatat dalam jawabannya - bahwa nilai untuk$var
ini sangat mungkin menghilang sepenuhnya bila{ current shell; }
pengelompokan adalah Tutup. Apakah ada cara yang lebih eksplisit untuk mengatakannya daripada, Apa pun yang Anda lakukan$var
menghilang ...?input | sed "s/'"'/&"&"&/g;s/.*/process2 '"'-> &'/" | sh
_variables
fungsibash_completion
, yang menyimpan hasil substitusi perintah dalam variabel globalCOMPREPLY
. Jika solusi saluran pipa digunakan untuk menjaga saluran baru, hasilnya akan hilang. Dalam jawaban Anda, orang memiliki kesan bahwa kedua solusi sama baiknya. Selain itu harus dicatat bahwa perilaku solusi pipa sangat tergantung pada shell: pengguna dapat mengujiecho foo | { var=$(sed '$s/$/./'); var=${var%.}; } ; echo $var
dengan ksh93 dan zsh, dan berpikir bahwa itu OK, sedangkan kode ini bermasalah.$var
menghilang" (yang sebenarnya tidak benar karena ini tergantung pada shell - perilaku tidak ditentukan oleh POSIX), yang merupakan kalimat yang agak netral. Solusi kedua lebih baik karena tidak menderita masalah ini, dan perilakunya konsisten di semua shell POSIX.