Tôi đã đi vòng quanh với điều này. Tôi đã thất vọng với tính di động của byte null. Nó không phù hợp với tôi rằng không có cách nào đáng tin cậy để xử lý chúng trong vỏ. Vì vậy, tôi tiếp tục tìm kiếm. Sự thật là tôi đã tìm thấy một số cách để làm điều này, chỉ một vài trong số đó được ghi chú trong câu trả lời khác của tôi. Nhưng kết quả có ít nhất hai hàm shell hoạt động như thế này:
_pidenv ${psrc=$$} ; _zedlmt <$near_any_type_of_file
Đầu tiên tôi sẽ nói về việc \0
phân định. Nó thực sự là khá dễ dàng để làm. Đây là chức năng:
_zedlmt() { od -t x1 -w1 -v | sed -n '
/.* \(..\)$/s//\1/
/00/!{H;b};s///
x;s/\n/\\x/gp;x;h'
}
Về cơ bản od
lấy stdin
và ghi vào stdout
từng byte của nó, nó nhận được một thập lục phân trên mỗi dòng.
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
Tôi cá là bạn có thể đoán đó là cái gì \0null
, phải không? Viết ra như thế thật dễ dàng để xử lý với bất kỳ sed
. sed
chỉ lưu hai ký tự cuối cùng trong mỗi dòng cho đến khi nó gặp null tại điểm mà nó thay thế các dòng mới trung gian bằng printf
mã định dạng thân thiện và in chuỗi. Kết quả là một \0null
mảng phân cách của các chuỗi byte hex. Nhìn:
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
.
Tôi đã dẫn đường ở trên để tee
bạn có thể thấy cả đầu ra của lệnh susbstlation và kết quả printf
xử lý. Tôi hy vọng bạn sẽ nhận thấy rằng phần con thực sự không được trích dẫn nhưng printf
vẫn chỉ được phân tách tại \0null
dấu phân cách. Nhìn:
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
.
Không có trích dẫn nào về bản mở rộng đó - không quan trọng bạn có trích dẫn hay không. Điều này là do các giá trị khớp thông qua không \n
tách rời ngoại trừ một ewline được tạo cho mỗi lần sed
in một chuỗi. Chia tách từ không áp dụng. Và đó là những gì làm cho điều này có thể:
_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
Việc sử dụng chức năng ở trên _zedlmt
hoặc là ${pcat}
một dòng suối chuẩn bị mã byte cho tìm nguồn cung ứng môi trường của bất kỳ quá trình có thể được tìm thấy trong /proc
, hoặc trực tiếp .dot
${psrc}
cùng trong vỏ hiện tại, hoặc không có tham số, để hiển thị một sản lượng chế biến của cùng với thiết bị đầu cuối như set
hoặc printenv
sẽ Tất cả bạn cần là một $pid
- bất kỳ/proc/$pid/environ
tập tin có thể đọc sẽ làm.
Bạn sử dụng nó như thế này:
#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}
Nhưng sự khác biệt giữa thân thiện với con người và nguồn gốc là gì? Chà, sự khác biệt ở đây là điều làm cho câu trả lời này khác với mọi câu hỏi khác ở đây - bao gồm cả câu trả lời khác của tôi. Mỗi câu trả lời khác phụ thuộc vào trích dẫn shell theo cách này hay cách khác để xử lý tất cả các trường hợp cạnh. Nó chỉ đơn giản là không hoạt động tốt. Xin hãy tin tôi - Tôi đã TRIỆT. Nhìn:
_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")
KHÔNG có số lượng ký tự sôi nổi hoặc trích dẫn có chứa có thể phá vỡ điều này bởi vì các byte cho mỗi giá trị không được đánh giá cho đến khi ngay lập tức nội dung có nguồn gốc. Và chúng ta đã biết nó hoạt động như một giá trị ít nhất một lần - không cần phân tích cú pháp hoặc bảo vệ trích dẫn ở đây vì đây là bản sao từng byte của giá trị ban đầu.
Trước tiên, hàm sẽ đánh giá các $var
tên và chờ kiểm tra hoàn tất trước khi .dot
tìm nguồn cung cấp tài liệu ở đây trên mô tả tệp 3. Trước khi nguồn đó trông giống như vậy. Đó là bằng chứng ngu ngốc. Và POSIX di động. Chà, ít nhất thì việc xử lý \ 0null là POSIX xách tay - hệ thống tập tin / process rõ ràng là đặc thù của Linux. Và đó là lý do tại sao có hai chức năng.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, sẽ xử lý các biến với dấu ngoặc kép đúng.