Article
· Fév 25 3m de lecture

Le terminateur de ligne ensorcelé

Je souhaite aborder les problèmes désagréables liés à la lecture d'un texte plat en ASCII, UTF*
excluant explicitement HTML, EBCDIC, et autres encodages.
D'après Wikipediail existe au moins 8 variantes de caractères de contrôle.

  • CR+LF est typique de Windows
  • LF est typique du monde Linux/UNIX
  • CR est le préféré de Mac

Comme vous pouvez le déduire des noms, l'inspiration vient des machines à écrire mécaniques.

Dans IRIS* comme dans Caché ou Ensemble ou ... les classes %Stream* et %File* offrent la même propriété avec la même valeur par défaut.


• La propriété LineTerminator as %String(MAXLEN=10) [ InitialExpression = $get(^%SYS("Stream","LineTerminator"),$select($$$isUNIX:$char(10),1:$char(13,10))),Transient ];

C'est assez confortable, tant que votre fichier provient du même système d'exploitation que celui sur lequel vous travaillez.
La situation devient plus délicate si vous ne définissez pas correctement le LineTerminator.

  • la lecture de texte de Linux/Unix (LF) dans Windows (CRLF) ne pose pas de problème
  • mais Windows (CRLF) vers Linux/Unix (LF) laisse la CR final à la fin de la ligne

Comment cela est-il possible ?

  • Si vous recevez votre fichier sur le réseau à partir de quelque part
  • Si vous travaillez avec Docker Desktop on Windows et utiliser un répertoire mappé
    • la valeur par défaut à l'extérieur du conteneur est (CRLF) alors qu'à l'intérieur elle est (LF) seulement
    • J'ai rencontré ce problème récemment, ce qui a entraîné une analyse de texte erronée.

Un autre obstacle caché des conteneurs Docker dans cette constellation est le suivant : bash

A l'intérieur de votre conteneur, vous êtes dans UBUNTU et le shell de commande est bash
En utilisant le mappage de volume, vous pouvez avoir un accès complet à un répertoire (extérieur) dans Windows
Le stockage d'un script shell dans ce répertoire peut utiliser (CRLF) comme terminaison de ligne.

bash n'aime pas du tout cela.

Il s'attend à une ligne droite (LF) et le reste (CR) provoque toutes sortes d'absurdités.

Exemple :

cp -v /home/irisowner/dev/somefile.yml /user/irissys/mgr/

  • fonctionne comme prévu dans un script shell terminé par Linux
  • produces sick filename '$'\r'  dans un script avec des terminateurs Windows

Comment savoir quel Terminateur de ligne j'ai reçu ?  - Tutoriel

  1. J'ouvre mon fichier en lecture avec une longueur d'enregistrement non définie.
    • set file="/home/irisowner/dev/iknow.yaml"
    • open file:"RU":0 if '$TEST quit  ;open failed
    •  
  2. Ensuite, je vais chercher quelque chose de probablement plus long qu'une ligne
    • read line#5000
    •  
  3. Ensuite, nous comptons (CR) et (LF)
    • set cr=$Length(line,$char(13))
    • set lf=$Length(line,$char(10)) 
  4. Lorsque vous voyez le même nombre de (CR) que de (LF), vous avez un texte Windows.
    • plus de (LF) que de (CR) indique un test formaté Linux/Unix
    • plus (CR) que (LF) découvre un texte formaté Mac
  5. Il ne s'agit que d'une première vérification qui ne vous protège pas des structures exotiques.

J'espère que cela vous aidera d'une manière ou d'une autre.
Je n'étais pas au courant avant et la sensibilité de bash m'a occupé pendant un certain temps pour le comprendre. 

Discussion (1)1
Connectez-vous ou inscrivez-vous pour continuer