Я ходил по кругу с этим. Я был разочарован переносимостью нулевых байтов. Мне не понравилось, что не было надежного способа справиться с ними в скорлупе. Так что я продолжал искать. Правда в том, что я нашел несколько способов сделать это, только несколько из которых отмечены в моем другом ответе. Но результатом были как минимум две функции оболочки, которые работают так:
_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чтобы вы могли видеть как вывод команды susbstitution, так и результат 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источник here-doc загрузит его в файл-дескриптор 3. Прежде чем получить его, он выглядит так. Это глупо. И POSIX портативный. Ну, по крайней мере, обработка \ 0null является переносимой POSIX - файловая система / process, очевидно, специфична для Linux. И вот почему есть две функции.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ), который будет правильно обрабатывать переменные с кавычками.