Pourquoi la tuyauterie en «queue» modifie-t-elle le contenu d'une ligne?

14

Quand je vois le résultat d'un SELECTavec MySQL Workbench, c'est correct avec un seul \

max@host 10:13:58: ~$ mysql -h db-master.domain.local -uuser -ppw db -e '
>                 SELECT
>                 DISTINCT i.filesourceregexp
>                 FROM db.ImportLogFiles i'

+------------------------------------------------+
| filesourceregexp                               |
+------------------------------------------------+
| ^[0-9]{8}_1062355673_merge_google_pbn\.csv$    |
| ^[0-9]{8}_8026062435_merge_google_pbn\.csv$    |
| ^[0-9]{8}_1062355673_store_visits_report\.csv$ |
+------------------------------------------------+

max@host 10:14:10: ~$ mysql -h db-master.domain.local -uuser -ppw db -e '
                SELECT
                DISTINCT i.filesourceregexp
                FROM db.ImportLogFiles i' | tail -n +2
^[0-9]{8}_1062355673_merge_google_pbn\\.csv$
^[0-9]{8}_8026062435_merge_google_pbn\\.csv$
^[0-9]{8}_1062355673_store_visits_report\\.csv$
max@host 10:14:19: ~$ 

J'ai ces options dans my.cnf:

[client] 
host = db-master 
user = user 
password = pass 
default-character-set=utf8

Pourquoi le fait de canaliser le résultat en tailmodifiant la sortie / chaîne? (notez le double \).

FaxMax
la source
Vous obtenez la même sortie si vous dirigez une autre commande, non? Par exemple mysql ... | headou mysql ... | grep 8?
terdon
Merci d'avoir amélioré mon anglais. headet grep 802doublez également le * \ * max@host 10:50:48: ~$ mysql -V mysql Ver 14.14 Distrib 5.5.55, for debian-linux-gnu (x86_64) using readline 6.3
FaxMax
quelle queue utilisez-vous? pouvez-vous partager la sortie detail --version
amisax
@amisax ma queue est tail (GNU coreutils) 8.23mais j'ai le même problème avec grep ou head
FaxMax
mon bash est GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)et uname -arésultats:Linux host 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2+deb8u2 (2017-06-26) x86_64 GNU/Linux
FaxMax

Réponses:

32

Ce n'est pas tail, c'est la tuyauterie.

mysqlutilise un tableau avec un format de sortie de boxe ASCII lorsque sa sortie standard est un périphérique terminal, lorsqu'il est destiné à un utilisateur, et revient à un format de script lorsqu'il ne l'est pas, comme lorsqu'il s'agit d'un canal ou d'un fichier normal.

Vous verriez le même format différent avec

mysql... | cat

ou

mysql > file; cat file

Voir aussi les -r/ --raw, -s/ --silent, -B/ --batch, -N/ --skip-column-names/ --column-names=0, -H/ --html, -t/ --table... qui affectent le format de sortie.

Si vous voulez la sortie tabulaire même lorsque la sortie ne va pas vers un terminal, ajoutez l' -toption:

mysql -t ... | tail -n +2

Mais si le but est de supprimer la ligne d'en-tête, utilisez simplement -N, avec ou sans -t.

Ici, pour obtenir les valeurs de la base de données aussi brutes que possible et sans en-tête, j'utiliserais:

mysql --defaults-extra-file=/some/protected/file/with/credentials \
      --batch --raw --skip-column-names -e 'select...' database

C'est:

  • ne pas exposer le mot de passe dans la sortie de psen passant les informations d'identification dans un fichier à la place (comme vous my.cnf) avec --defaults-extra-file.
  • utilisez le mode batch pour éviter la sortie tabulaire (et reconnaissez le fait que nous sommes en train de le batcher ce qui peut avoir d'autres implications).
  • --rawpour éviter la fuite . En supposant que les valeurs ne contiennent pas de sauts de ligne, sinon la sortie ne pourrait pas être post-traitée de manière fiable.
  • --skip-column-names pour supprimer la ligne d'en-tête.
Stéphane Chazelas
la source
1
les options ont -r --column-names=0résolu mon problème, réservoirs
FaxMax
3
C'est la même raison pour laquelle la lssortie est placée dans des colonnes lorsque la sortie va vers un terminal, mais c'est une seule colonne lors de l'écriture dans un canal ou un fichier.
Barmar