Ich bin damit herumgegangen. Ich war mit der Portabilität von Null-Bytes frustriert. Es war nicht gut für mich, dass es keine zuverlässige Möglichkeit gab, mit ihnen in einer Muschel umzugehen. Also suchte ich weiter. Die Wahrheit ist, dass ich verschiedene Wege gefunden habe, von denen nur einige in meiner anderen Antwort aufgeführt sind. Das Ergebnis waren jedoch mindestens zwei Shell-Funktionen, die folgendermaßen funktionieren:
_pidenv ${psrc=$$} ; _zedlmt <$near_any_type_of_file
Zuerst werde ich über die \0
Abgrenzung sprechen . Das ist eigentlich ganz einfach. Hier ist die Funktion:
_zedlmt() { od -t x1 -w1 -v | sed -n '
/.* \(..\)$/s//\1/
/00/!{H;b};s///
x;s/\n/\\x/gp;x;h'
}
Nimmt od
im Grunde genommen jedes Byte stdin
und schreibt stdout
es in hexadezimal eins pro Zeile.
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
Ich wette, Sie können sich vorstellen, welches das ist \0null
, oder? So geschrieben ist es einfach mit jedem umzugehen sed
. sed
Speichert nur die letzten zwei Zeichen in jeder Zeile, bis eine Null gefunden wird. An diesem Punkt werden die Zwischenzeilen durch einen benutzerfreundlichen Formatcode ersetzt printf
und die Zeichenfolge gedruckt. Das Ergebnis ist ein \0null
begrenztes Array von Hex-Byte-Zeichenfolgen. Aussehen:
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
.
Ich habe das Obige weitergeleitet, tee
damit Sie sowohl die Ausgabe der Befehlsaufhebung als auch das Ergebnis der printf
Verarbeitung sehen können. Ich hoffe, Sie werden feststellen, dass die Subshell auch nicht in Anführungszeichen steht, sondern printf
nur am \0null
Begrenzer geteilt ist. Aussehen:
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
.
Auch zu dieser Erweiterung gibt es keine Anführungszeichen - es spielt keine Rolle, ob Sie sie zitieren oder nicht. Dies liegt daran, dass die \n
Bisswerte mit Ausnahme der einen E-Zeile, die jedes Mal generiert wird, wenn sed
eine Zeichenfolge gedruckt wird, nicht getrennt durchlaufen werden . Wortteilung gilt nicht. Und das macht es möglich:
_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
Die obige Funktion verwendet _zedlmt
entweder ${pcat}
einen vorbereiteten Strom von Byte-Code für das Beschaffen von Umgebungen für einen beliebigen Prozess, der sich in der aktuellen Shell befindet, oder /proc
direkt .dot
${psrc}
denselben oder ohne Parameter, um eine verarbeitete Ausgabe desselben für das Terminal anzuzeigen set
oder printenv
wird. Alles was Sie brauchen ist eine $pid
- jede lesbare /proc/$pid/environ
Datei reicht aus.
Du benutzt es so:
#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}
Aber was ist der Unterschied zwischen menschenfreundlich und säuerlich ? Nun, der Unterschied besteht darin, was diese Antwort anders macht als alle anderen hier - einschließlich meiner anderen. Jede andere Antwort hängt davon ab, dass die Shell auf die eine oder andere Weise zitiert, um alle Randfälle zu behandeln. Es funktioniert einfach nicht so gut. Bitte glauben Sie mir - ich habe es versucht. Aussehen:
_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")
KEINE Menge von unkonventionellen Zeichen oder Anführungszeichen kann dies stören, da die Bytes für jeden Wert erst ausgewertet werden, wenn der Inhalt in dem Moment bezogen wird, in dem er stammt. Und wir wissen bereits, dass es mindestens einmal als Wert funktioniert hat - hier ist kein Parsen oder Anführungszeichen erforderlich, da dies eine byteweise Kopie des ursprünglichen Werts ist.
Die Funktion wertet zuerst die $var
Namen aus und wartet, bis die Überprüfungen abgeschlossen sind, bevor .dot
das hier angegebene Dokument in Dateideskriptor 3 eingespeist wird. Es ist narrensicher. Und POSIX portabel. Nun, zumindest die \ 0null-Behandlung ist POSIX-portierbar - das / process-Dateisystem ist offensichtlich Linux-spezifisch. Und deshalb gibt es zwei Funktionen.
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, dass Variablen mit Anführungszeichen auch richtig behandelt werden.