Я ходил по кругу с этим. Я был разочарован переносимостью нулевых байтов. Мне не понравилось, что не было надежного способа справиться с ними в скорлупе. Так что я продолжал искать. Правда в том, что я нашел несколько способов сделать это, только несколько из которых отмечены в моем другом ответе. Но результатом были как минимум две функции оболочки, которые работают так:
_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)
, который будет правильно обрабатывать переменные с кавычками.