J'ai tourné en rond avec ça. J'étais frustré par la portabilité des octets nuls. Cela ne me convenait pas qu'il n'y avait aucun moyen fiable de les manipuler dans une coquille. J'ai donc continué à chercher. La vérité est que j'ai trouvé plusieurs façons de le faire, dont seulement quelques-unes sont mentionnées dans mon autre réponse. Mais les résultats ont été au moins deux fonctions shell qui fonctionnent comme ceci:
_pidenv ${psrc=$$} ; _zedlmt <$near_any_type_of_file
Je vais d'abord parler de la \0délimitation. C'est en fait assez facile à faire. Voici la fonction:
_zedlmt() { od -t x1 -w1 -v | sed -n '
/.* \(..\)$/s//\1/
/00/!{H;b};s///
x;s/\n/\\x/gp;x;h'
}
Fondamentalement odprend stdinet écrit à son stdoutchaque octet qu'il reçoit en hexadécimal une par ligne.
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
Je parie que vous pouvez deviner quel est le \0nullbon, non? Écrit comme ça, il est facile à manipuler avec tout sed . sedenregistre simplement les deux derniers caractères de chaque ligne jusqu'à ce qu'il rencontre une valeur nulle à quel point il remplace les sauts de ligne intermédiaires par printfun code de format convivial et imprime la chaîne. Le résultat est un \0nulltableau délimité de chaînes d'octets hexadécimales. Regardez:
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
.
J'ai expliqué ce qui précède pour teeque vous puissiez voir à la fois la sortie de la substitution de commande et le résultat du printftraitement de. J'espère que vous remarquerez que le sous-shell n'est pas cité non plus, mais qu'il est printftoujours divisé uniquement au niveau du \0nulldélimiteur. Regardez:
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
.
Aucune citation sur cette extension non plus - peu importe si vous la citez ou non. Cela est dû au fait que les valeurs de morsure ne sont pas séparées, à l'exception de la ligne \nélectronique générée pour chaque fois qui sedimprime une chaîne. Le fractionnement de mots ne s'applique pas. Et c'est ce qui rend cela possible:
_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
La fonction ci-dessus utilise _zedlmtsoit ${pcat}un flux préparé de code d'octet pour l'approvisionnement de l'environnement de tout processus qui peut être trouvé dans /proc, soit directement .dot ${psrc}le même dans le shell actuel, ou sans paramètre, pour afficher une sortie traitée de celui-ci vers le terminal comme setou le printenvfera. Tout ce dont vous avez besoin est d'un $pid- n'importe quel/proc/$pid/environ fichier lisible fera l'affaire.
Vous l'utilisez comme ceci:
#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}
Mais quelle est la différence entre convivial et sourcable ? Eh bien, la différence est ce qui rend cette réponse différente de toutes les autres ici - y compris la mienne. Toutes les autres réponses dépendent du shell citant d'une manière ou d'une autre pour gérer tous les cas de bord. Cela ne fonctionne tout simplement pas si bien. Croyez-moi, j'ai ESSAYÉ. Regardez:
_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")
AUCUNE quantité de caractères géniaux ou de guillemets contenus ne peut casser cela car les octets de chaque valeur ne sont évalués qu'au moment même où le contenu est recherché. Et nous savons déjà que cela a fonctionné comme valeur au moins une fois - il n'y a pas de protection d'analyse ou de citation nécessaire ici car il s'agit d'une copie octet par octet de la valeur d'origine.
La fonction évalue d'abord les $varnoms et attend que les vérifications soient terminées avant de se .dotprocurer le here-doc qui l'a alimenté sur le descripteur de fichier 3. Avant de le rechercher, c'est à quoi il ressemble. C'est infaillible. Et POSIX portable. Eh bien, au moins la gestion \ 0null est POSIX portable - le système de fichiers / process est évidemment spécifique à Linux. Et c'est pourquoi il y a deux fonctions.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ), qui gérera également les variables avec des guillemets correctement.