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 \0Abgrenzung 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 odim Grunde genommen jedes Byte stdinund schreibt stdoutes 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 . sedSpeichert nur die letzten zwei Zeichen in jeder Zeile, bis eine Null gefunden wird. An diesem Punkt werden die Zwischenzeilen durch einen benutzerfreundlichen Formatcode ersetzt printfund die Zeichenfolge gedruckt. Das Ergebnis ist ein \0nullbegrenztes 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, teedamit Sie sowohl die Ausgabe der Befehlsaufhebung als auch das Ergebnis der printfVerarbeitung sehen können. Ich hoffe, Sie werden feststellen, dass die Subshell auch nicht in Anführungszeichen steht, sondern printfnur am \0nullBegrenzer 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 \nBisswerte mit Ausnahme der einen E-Zeile, die jedes Mal generiert wird, wenn sedeine 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 _zedlmtentweder ${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 /procdirekt .dot ${psrc}denselben oder ohne Parameter, um eine verarbeitete Ausgabe desselben für das Terminal anzuzeigen setoder printenvwird. Alles was Sie brauchen ist eine $pid- jede lesbare /proc/$pid/environDatei 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 $varNamen aus und wartet, bis die Überprüfungen abgeschlossen sind, bevor .dotdas 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.