Chodziłem z tym po kółku. Byłem sfrustrowany przenośnością zerowych bajtów. Nie podobało mi się to, że nie było niezawodnego sposobu na obsłużenie ich w skorupce. Więc szukałem dalej. Prawda jest taka, że znalazłem kilka sposobów, aby to zrobić, z których tylko kilka zostało odnotowanych w mojej drugiej odpowiedzi. Ale rezultatem były co najmniej dwie funkcje powłoki, które działają w ten sposób:
_pidenv ${psrc=$$} ; _zedlmt <$near_any_type_of_file
Najpierw porozmawiam o \0rozgraniczeniu. To jest naprawdę łatwe do zrobienia. Oto funkcja:
_zedlmt() { od -t x1 -w1 -v | sed -n '
/.* \(..\)$/s//\1/
/00/!{H;b};s///
x;s/\n/\\x/gp;x;h'
}
Zasadniczo odpobiera stdini zapisuje do stdoutkażdego otrzymanego bajtu w systemie szesnastkowym po jednym w wierszu.
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
Założę się, że możesz zgadnąć, co jest \0null, prawda? Tak napisane jest łatwe w obsłudze z każdym sed . sedpo prostu zapisuje dwa ostatnie znaki w każdej linii, aż napotka zero, w którym to miejscu zastępuje nowe znaki pośrednie printfkodem przyjaznego formatu i wypisuje ciąg. Wynikiem jest \0nullrozdzielona tablica ciągów bajtów szesnastkowych. Popatrz:
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
.
Przetokowałem powyższe, aby teemożna było zobaczyć zarówno wynik działania polecenia, jak i wynik printfjego przetwarzania. Mam nadzieję, że zauważysz, że podpowłoka faktycznie nie jest cytowana, ale printfnadal dzieli się tylko na \0nullograniczniku. Popatrz:
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
.
Brak cytatów na temat tego rozszerzenia - nie ma znaczenia, czy go zacytujesz, czy nie. Wynika to z tego, że wartości zgryzu są \nrozdzielane osobno, z wyjątkiem jednej linii ewline generowanej za każdym razem, gdy seddrukuje łańcuch. Podział słów nie ma zastosowania. I to sprawia, że jest to możliwe:
_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
Powyższa funkcja używa _zedlmtalbo ${pcat}do przygotowanego strumienia kodu bajtowego do pozyskiwania środowiska dowolnego procesu, który można znaleźć w /proc, lub bezpośrednio do .dot ${psrc}tego samego w bieżącej powłoce lub bez parametru, aby wyświetlić przetworzone wyjście tego samego na terminalu, takie jak setlub printenvbędzie. Wszystko czego potrzebujesz to $pid- zrobi każdy czytelny /proc/$pid/environplik.
Używasz go w ten sposób:
#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}
Ale jaka jest różnica między człowiekiem przyjaznym a zasobnym ? Różnica polega na tym, że ta odpowiedź różni się od wszystkich tutaj - w tym mojej drugiej. Każda inna odpowiedź zależy w jakiś sposób od cytowania powłoki w celu obsłużenia wszystkich przypadków krawędzi. Po prostu nie działa tak dobrze. Proszę uwierz mi - SPRÓBOWAŁEM. Popatrz:
_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")
ŻADNA liczba funky znaków lub zawartych cytatów nie może tego zepsuć, ponieważ bajty dla każdej wartości nie są obliczane aż do momentu, gdy zawartość jest pobierana. Wiemy już, że przynajmniej raz działała jako wartość - nie ma tu potrzeby analizy składni ani cytowania, ponieważ jest to kopia bajt po bajcie oryginalnej wartości.
Ta funkcja najpierw ocenia $varnazwy i czeka na zakończenie kontroli, zanim .dotsourcing dokona tego tutaj, podając go deskryptorowi pliku 3. Zanim zacznie źródła, tak to wygląda. Jest głupi. I przenośny POSIX. Cóż, przynajmniej obsługa \ 0null jest przenośna POSIX - system plików / process jest oczywiście specyficzny dla Linuksa. I dlatego są dwie funkcje.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ), który również odpowiednio obsługuje zmienne z cudzysłowami.