Я з цим ходив кругом. Мене розчарувало перенесення нульових байтів. Зі мною не було добре, що не було надійного способу поводження з ними в оболонці. Тому я продовжував шукати. Правда в тому, що я знайшов кілька способів зробити це, лише пару з них відзначені в моїй іншій відповіді. Але в результаті були принаймні дві функції оболонки, які працюють так:
_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дружним кодом формату та надрукує рядок. Результат - це \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
.
Немає жодних цитат щодо цього розширення - не має значення, цитуєте ви його чи ні. Це пояснюється тим, що значення прикусу надходять через нерозділене, за винятком однієї \newline, що створюється для кожного разу, 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 - файлова система / process очевидно специфічна для Linux. І тому є дві функції.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ), які також будуть обробляти змінні з цитатами в них належним чином.