Saya berputar-putar dengan ini. Saya frustrasi dengan portabilitas byte nol. Itu tidak cocok dengan saya bahwa tidak ada cara yang dapat diandalkan untuk menangani mereka dalam cangkang. Jadi saya terus mencari. Yang benar adalah saya menemukan beberapa cara untuk melakukan ini, hanya beberapa di antaranya yang dicatat dalam jawaban saya yang lain. Tetapi hasilnya setidaknya dua fungsi shell yang bekerja seperti ini:
_pidenv ${psrc=$$} ; _zedlmt <$near_any_type_of_file
Pertama saya akan berbicara tentang \0pembatas. Ini sebenarnya cukup mudah dilakukan. Inilah fungsinya:
_zedlmt() { od -t x1 -w1 -v | sed -n '
/.* \(..\)$/s//\1/
/00/!{H;b};s///
x;s/\n/\\x/gp;x;h'
}
Pada dasarnya odmengambil stdindan menulis ke stdoutsetiap byte yang diterimanya dalam heksadesimal satu per baris.
printf 'This\0is\0a\0lot\0\of\0\nulls.' |
od -t x1 -w1 -v
#output
0000000 54
0000001 68
0000002 69
0000003 73
0000004 00
0000005 69
0000006 73
#and so on
Saya yakin Anda bisa menebak yang mana \0null, kan? Ditulis seperti itu sangat mudah untuk menangani dengan setiap sed . sedhanya menyimpan dua karakter terakhir di setiap baris sampai menemukan nol di mana titik itu menggantikan baris baru menengah dengan printfkode format ramah dan mencetak string. Hasilnya adalah \0nullarray yang dibatasi string hex byte. Melihat:
printf %b\\n $(printf 'Fewer\0nulls\0here\0.' |
_zedlmt | tee /dev/stderr)
#output
\x46\x65\x77\x65\x72
\x6e\x75\x6c\x6c\x73
\x68\x65\x72\x65
\x2e
Fewer
nulls
here
.
Saya mengirim pipa di atas teesehingga Anda bisa melihat output susbstitusi perintah dan hasil printfpemrosesan. Saya harap Anda akan melihat bahwa subkulit sebenarnya tidak dikutip juga tetapi printfmasih dibagi hanya pada \0nullpembatas. Melihat:
printf %b\\n $(printf \
"Fe\n\"w\"er\0'nu\t'll\\'s\0h ere\0." |
_zedlmt | tee /dev/stderr)
#output
\x46\x65\x0a\x22\x77\x22\x65\x72
\x27\x6e\x75\x09\x27\x6c\x6c\x27\x73
\x68\x20\x20\x20\x20\x65\x72\x65
\x2e
Fe
"w"er
'nu 'll's
h ere
.
Tidak ada kutipan pada ekspansi itu - tidak masalah apakah Anda mengutipnya atau tidak. Ini karena nilai gigitan yang \ndihasilkan tidak terpisahkan kecuali untuk satu baris yang dihasilkan untuk setiap kali sedmencetak string. Pemisahan kata tidak berlaku. Dan itulah yang memungkinkan ini terjadi:
_pidenv() { ps -p $1 >/dev/null 2>&1 &&
[ -z "${1#"$psrc"}" ] && . /dev/fd/3 ||
cat <&3 ; unset psrc pcat
} 3<<STATE
$( [ -z "${1#${pcat=$psrc}}" ] &&
pcat='$(printf %%b "%s")' || pcat="%b"
xeq="$(printf '\\x%x' "'=")"
for x in $( _zedlmt </proc/$1/environ ) ; do
printf "%b=$pcat\n" "${x%%"$xeq"*}" "${x#*"$xeq"}"
done)
#END
STATE
Fungsi di atas digunakan _zedlmtuntuk ${pcat}aliran kode byte yang disiapkan untuk sumber lingkungan dari setiap proses yang dapat ditemukan di /proc, atau untuk secara langsung .dot ${psrc}sama di shell saat ini, atau tanpa parameter, untuk menampilkan output yang diproses sama ke terminal seperti setatau printenvakan. Yang Anda butuhkan adalah $pid- file apa pun yang dapat dibaca /proc/$pid/environakan dilakukan.
Anda menggunakannya seperti ini:
#output like printenv for any running process
_pidenv $pid
#save human friendly env file
_pidenv $pid >/preparsed/env/file
#save unparsed file for sourcing at any time
_pidenv ${pcat=$pid} >/sourcable/env.save
#.dot source any pid's $env from any file stream
_pidenv ${pcat=$pid} | sh -c '. /dev/stdin'
#feed any pid's env in on a heredoc filedescriptor
su -c '. /dev/fd/4' 4<<ENV
$( _pidenv ${pcat=$pid} )
ENV
#.dot sources any $pid's $env in the current shell
_pidenv ${psrc=$pid}
Tetapi apa perbedaan antara ramah manusia dan sumber daya ? Nah, perbedaannya adalah apa yang membuat jawaban ini berbeda dari yang lain di sini - termasuk yang lain. Setiap jawaban lainnya tergantung pada shell mengutip dalam beberapa cara atau yang lain untuk menangani semua kasus tepi. Itu tidak bekerja dengan baik. Tolong percayalah - saya sudah MENCOBA. Melihat:
_pidenv ${pcat=$$}
#output
LC_COLLATE=$(printf %b "\x43")
GREP_COLOR=$(printf %b "\x33\x37\x3b\x34\x35")
GREP_OPTIONS=$(printf %b "\x2d\x2d\x63\x6f\x6c\x6f\x72\x3d\x61\x75\x74\x6f")
LESS_TERMCAP_mb=$(printf %b "\x1b\x5b\x30\x31\x3b\x33\x31\x6d")
LESS_TERMCAP_md=$(printf %b "\x1b\x5b\x30\x31\x3b\x33\x31\x6d")
LESS_TERMCAP_me=$(printf %b "\x1b\x5b\x30\x6d")
LESS_TERMCAP_se=$(printf %b "\x1b\x5b\x30\x6d")
LESS_TERMCAP_so=$(printf %b "\x1b\x5b\x30\x30\x3b\x34\x37\x3b\x33\x30\x6d")
LESS_TERMCAP_ue=$(printf %b "\x1b\x5b\x30\x6d")
TIDAK ada jumlah karakter yang funky atau kutipan yang terkandung dapat mematahkan ini karena byte untuk setiap nilai tidak dievaluasi sampai saat konten diambil. Dan kita sudah tahu itu berfungsi sebagai nilai setidaknya sekali - tidak ada penguraian atau perlindungan kutipan yang diperlukan di sini karena ini adalah salinan byte-untuk-byte dari nilai aslinya.
Fungsi pertama mengevaluasi $varnama - nama dan menunggu untuk menyelesaikan cek sebelum .dotsumber di sini-dok di-deskriptor pada file 3. Sebelum sumber itu, itu seperti apa itu. Ini bukti bodoh. Dan POSIX portable. Yah, setidaknya penanganan \ 0null adalah POSIX portable - filesystem / proses jelas spesifik untuk Linux. Dan itu sebabnya ada dua fungsi.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ), yang akan menangani variabel dengan tanda kutip di dalamnya dengan benar juga.