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 \0
pembatas. 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 od
mengambil stdin
dan menulis ke stdout
setiap 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
. sed
hanya menyimpan dua karakter terakhir di setiap baris sampai menemukan nol di mana titik itu menggantikan baris baru menengah dengan printf
kode format ramah dan mencetak string. Hasilnya adalah \0null
array 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 tee
sehingga Anda bisa melihat output susbstitusi perintah dan hasil printf
pemrosesan. Saya harap Anda akan melihat bahwa subkulit sebenarnya tidak dikutip juga tetapi printf
masih dibagi hanya pada \0null
pembatas. 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 \n
dihasilkan tidak terpisahkan kecuali untuk satu baris yang dihasilkan untuk setiap kali sed
mencetak 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 _zedlmt
untuk ${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 set
atau printenv
akan. Yang Anda butuhkan adalah $pid
- file apa pun yang dapat dibaca /proc/$pid/environ
akan 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 $var
nama - nama dan menunggu untuk menyelesaikan cek sebelum .dot
sumber 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.