2015-04-27 3 views
3

Compte tenu de ce fichierlire les champs délimités par NUL

printf 'alpha\0bravo\0charlie' > delta.txt 

Je voudrais lire les champs en variables distinctes. La raison pour laquelle j'utilise un séparateur nul est parce que les champs contiendront des chemins de fichier, qui peuvent contenir n'importe quel caractère sauf null. J'ai essayé ces commandes:

IFS= read mike november oscar < delta.txt 
IFS=$'\0' read mike november oscar < delta.txt 

Cependant, les champs ne sont pas correctement répartis

$ echo $mike 
alphabravocharlie 
+0

Je ne crois pas qu'un chemin de fichier contient un caractère sauf nul. – Marichyasana

Répondre

1

Pour contourner ce problème, j'ai créé cette fonction

function read_loop { 
    while [ "$#" -gt 0 ] 
    do 
    read -d '' "$1" 
    shift 
    done 
} 

Exemple d'utilisation

read-nul mike november oscar < delta.txt 
2

L'affectation IFS=$'\0' ne fait pas le caractère nul délimiteur, depuis Bash variables cannot hold null characters. IFS=$'\0' est équivalent à IFS=, que vous pouvez vérifier en faisant:

bash-4.3$ IFS=$'\0' 
bash-4.3$ echo ${#IFS} 
0 

Et IFS= par définition signifie pas la séparation de mots du tout (voir Bash Reference Manual).

Ce que vous pouvez faire est de lire les éléments délimités par zéro un par un en utilisant l'option -d du read builtin. Selon la documentation liée,

-d delim

Le premier caractère de delim est utilisé pour mettre fin à la ligne d'entrée, plutôt que de retour à la ligne.

Nous pouvons utiliser une chaîne nulle pour delim pour obtenir le comportement souhaité.

Exemple (je pris la liberté d'ajouter des espaces à votre exemple pour montrer comment il réalise ce qu'il veut - pas de fractionnement sur les espaces):

bash-4.3$ printf 'alpha with whitespace\0bravo with whitespace\0charlie with whitespace' > delta.txt 
bash-4.3$ { read -r -d '' mike; IFS= read -r -d '' november; IFS= read -r -d '' oscar; echo $mike; echo $november; echo $oscar; } < delta.txt 
alpha with whitespace 
bravo with whitespace 
charlie with whitespace 

J'utilise aussi l'option -r pour préserver antislash le fichier d'entrée. Bien sûr, vous pouvez remplacer < delta.txt par un cat delta.txt | au début. Je sais lire un par un est ennuyeux, mais je ne peux pas penser à quelque chose de mieux.

+0

Ceci est couvert (entre autres choses) sur http://mywiki.wooledge.org/BashFAQ/001. –

+0

@EtanReisner Oui, merci pour une autre référence. – 4ae1e1