Durch NUL getrennte Variable

Durch NUL getrennte Variable

GNU Bash, Version 4.4.19(1)-Release (x86_64-pc-linux-gnu)

Die Idee ist, eine Variable auf einen durch NUL getrennten Datensatz zu setzen. Hier$samples

Dies führt jedoch zu:

Warnung: Befehlsersetzung: Null-Byte in der Eingabe ignoriert

wenn Sie Folgendes tun:

samples="$(find . -type d -iregex './sample[0-9][0-9]' -printf "%f\0" | sort -z)"

Ich dachte, ich könnte diese Variable wiederverwenden, da ich dieselben Werte mehrmals iterieren muss:

while IFS= read -rd '' sample; do
    echo $sample
done<<< "$samples"

Ich könnte \ndrüben \0imfindenBefehl in genau diesem Fall, würde aber gerne wissen, wie man es, wenn möglich, generell mit dem NUL-Trennzeichen macht.

Optional könnte ich Folgendes tun:

while IFS= read -rd '' sample; do
    echo $sample
done< <(find . -type d -iregex './E[0-9][0-9]' -printf "%f\0" | sort -z)

aber - da ich es mehrere Male schleifen muss, ergibt das sehr redundanten Code - und ich müsste dasfindenUndSortierenBefehl jedes Mal.

Das Ergebnis vielleicht in ein Array umwandeln?


  • Ist das möglich?
  • Warum können durch NUL getrennte Daten nicht unverändert verwendet werden?

Antwort1

\0Es ist eine Tatsache, dass Sie aufgrund der zugrunde liegenden C-Implementierung keine Nullbytes in einem Bash-String-Kontext speichern können . SieheWarum ist $'\0' oder $'\x0' eine leere Zeichenfolge? Sollte doch das Nullzeichen sein, oder?.

Eine Möglichkeit wäre, die Nullbytes nach dem Sortierbefehl am Ende der Pipeline zu entfernen trund das Ergebnis zu speichern, um das unmittelbare Problem der ausgegebenen Warnmeldung zu lösen. Aber das würde Ihre Logik immer noch fehlerhaft lassen, da die Dateinamen mit Zeilenumbrüchen immer noch beschädigt wären.

Verwenden Sie ein Array, verwenden Sie den Befehl mapfileoder readarray(unter Bash 4.4+), um die Ergebnisse des findBefehls direkt einzuschlürfen

IFS= readarray -t -d '' samples < <(find . -type d -iregex './sample[0-9][0-9]' -printf "%f\0" | sort -z)

Antwort2

Die bashShell unterstützt nicht, was Sie tun möchten. Die zshShell unterstützt dies standardmäßig.

% mkdir sample11 SAMple12 sample21 sample22 dir1
% ll
total 20
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 dir1
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample11
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 SAMple12
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample21
drwxrwxr-x 2 fpm fpm 4096 Jun  9 13:46 sample22
% samples=$(find . -type d -iregex './sample[0-9][0-9]' -print0 | sort -z)
% echo $samples
./sample11./SAMple12./sample21./sample22
% echo $samples | od -a
0000000   .   /   s   a   m   p   l   e   1   1 nul   .   /   S   A   M
0000020   p   l   e   1   2 nul   .   /   s   a   m   p   l   e   2   1
0000040 nul   .   /   s   a   m   p   l   e   2   2 nul  nl
0000055
%

verwandte Informationen