मैं इसके साथ चक्कर लगाता गया। मैं अशक्त बाइट्स की पोर्टेबिलिटी से निराश था। यह मेरे साथ अच्छी तरह से नहीं बैठा था कि उन्हें शेल में संभालने का कोई विश्वसनीय तरीका नहीं था। इसलिए मैं देखता रहा। सच्चाई यह है कि मुझे ऐसा करने के कई तरीके मिले हैं, जिनमें से केवल एक जोड़े को मेरे अन्य उत्तर में नोट किया गया है। लेकिन परिणाम कम से कम दो शेल फ़ंक्शन थे जो इस तरह से काम करते हैं:
_pidenv ${psrc=$$} ; _zedlmt <$near_any_type_of_file
पहले मैं \0
परिसीमन के बारे में बात करूंगा । यह वास्तव में करने के लिए बहुत आसान है। यहाँ समारोह है:
_zedlmt() { od -t x1 -w1 -v | sed -n '
/.* \(..\)$/s//\1/
/00/!{H;b};s///
x;s/\n/\\x/gp;x;h'
}
मूल रूप से अपने प्रत्येक बाइट को लिखता od
है stdin
और stdout
इसे प्रति पंक्ति एक हेक्साडेसिमल में प्राप्त करता है।
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
मुझे यकीन है आप अनुमान लगा सकते हैं कि कौन सा है \0null
, है ना? इस तरह से लिखा गया है कि किसी भी के साथ संभालना आसान है sed
। sed
बस प्रत्येक पंक्ति में अंतिम दो वर्णों को बचाता है जब तक कि यह एक शून्य का सामना नहीं करता है जिस बिंदु पर यह printf
अनुकूल प्रारूप कोड के साथ मध्यवर्ती newlines को प्रतिस्थापित करता है और स्ट्रिंग को प्रिंट करता है। परिणाम \0null
हेक्स बाइट स्ट्रिंग्स का एक सीमांकित सरणी है। देखो:
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
.
मैंने ऊपर पाइप किया है tee
ताकि आप दोनों कमांड सुसेबस्ट्रेशन का आउटपुट और printf
प्रोसेसिंग का परिणाम देख सकें । मुझे आशा है कि आप देखेंगे कि वास्तव में उप-भाग या तो उद्धृत नहीं किया गया है, लेकिन फिर printf
भी केवल \0null
सीमांकक में विभाजित है। देखो:
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
.
उस विस्तार पर कोई उद्धरण या तो नहीं है - इससे कोई फर्क नहीं पड़ता कि आप इसे उद्धृत करते हैं या नहीं। ऐसा इसलिए होता है क्योंकि \n
प्रत्येक समय के लिए उत्पन्न ईवलाइन को छोड़कर काटे गए मान बिना sed
किसी तार के निकलते हैं । शब्द-विभाजन लागू नहीं होता है। और यही संभव बनाता है:
_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
उपरोक्त फ़ंक्शन किसी भी प्रक्रिया के पर्यावरण सोर्सिंग के लिए बाइट कोड की _zedlmt
या तो ${pcat}
एक तैयार स्ट्रीम का उपयोग करता है जो टर्मिनल में उसी के रूप में संसाधित आउटपुट को प्रदर्शित करने के लिए, या मौजूदा शेल में /proc
सीधे .dot
${psrc}
, या बिना पैरामीटर के समान हो सकता है। set
या printenv
होगा। आप सभी की जरूरत है $pid
- किसी भी पठनीय /proc/$pid/environ
फ़ाइल करना होगा।
आप इसे इस तरह उपयोग करते हैं:
#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}
लेकिन मानव के अनुकूल और खट्टा के बीच अंतर क्या है ? खैर, वहाँ अंतर यह है कि इस उत्तर को हर दूसरे की तुलना में अलग बनाता है - जिसमें मेरा दूसरा भी शामिल है। प्रत्येक अन्य उत्तर शेल या सभी किनारे के मामलों को संभालने के लिए किसी न किसी तरह से उद्धृत करने पर निर्भर करता है। यह बस अच्छी तरह से काम नहीं करता है। कृपया मुझ पर विश्वास करें - मैंने कोशिश की है। देखो:
_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")
कायरता पात्रों की कोई राशि या निहित उद्धरण इसे तोड़ सकते हैं क्योंकि प्रत्येक मूल्य के बाइट्स का मूल्यांकन तब तक नहीं किया जाता है जब तक कि सामग्री बहुत ही त्वरित रूप से खट्टी न हो जाए। और हम पहले से ही जानते हैं कि यह कम से कम एक बार एक मूल्य के रूप में काम करता है - यहां कोई पार्सिंग या बोली सुरक्षा आवश्यक नहीं है क्योंकि यह मूल मूल्य की एक बाइट-फॉर-बाइट कॉपी है।
फ़ंक्शन पहले $var
नामों का मूल्यांकन करता है और चेक के पूरा होने का इंतजार करता है, इससे पहले .dot
कि यहां-डॉक्स को फाइल-डिस्क्रिप्टर पर फीड किया जाए, 3. इससे पहले कि यह जैसा दिखता है, वैसा ही हो। यह मूर्खतापूर्ण है। और POSIX पोर्टेबल। ठीक है, कम से कम \ 0null हैंडलिंग POSIX पोर्टेबल है - / प्रक्रिया फ़ाइल सिस्टम स्पष्ट रूप से लिनक्स विशिष्ट है। और इसीलिए दो कार्य हैं।
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, जो उनके साथ ही ठीक से उद्धरण के साथ चर को संभाल लेंगे।