GNU/Linux >> Tutoriels Linux >  >> Linux

Une commande pour afficher chaque ligne vers l'avant puis vers l'arrière

Une fonction shell. Cela fonctionnera dans n'importe quel shell prenant en charge <<< chaînes ici, y compris zsh et bash.

xyz() { 
    while read line
    do 
        printf "%s " "$line"
        "[email protected]" <<<"$line"
    done
}
$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab

Il y aura beaucoup de problèmes dans la plupart des cas en raison du fonctionnement de la mise en mémoire tampon stdio. Une solution de contournement pour Linux pourrait être d'utiliser le stdbuf programmez et exécutez la commande avec coproc, afin que vous puissiez contrôler explicitement l'entrelacement de la sortie.

Ce qui suit suppose que la commande affichera une ligne après chaque ligne d'entrée.

#!/bin/bash
coproc stdbuf -i0 -o0 "[email protected]"
IFS=
while read -r in ; do
    printf "%s " "$in"
    printf "%s\n" "$in" >&${COPROC[1]}
    read -r out <&${COPROC[0]}
    printf "%s\n" "$out"
done

Si une solution plus générale est nécessaire car l'OP ne nécessitait que chaque ligne d'entrée du programme pour éventuellement sortie une ligne plutôt qu'immédiatement, alors une approche plus compliquée est nécessaire. Créer une boucle d'événement en utilisant read -t 0 pour essayer de lire à partir de stdin et du co-processus, si vous avez le même "numéro de ligne" pour les deux, sortez, sinon stockez la ligne. Pour éviter d'utiliser 100 % du processeur si, à aucun tour de la boucle d'événements, aucun n'était prêt, introduisez un petit délai avant d'exécuter à nouveau la boucle d'événements. Il y a des complications supplémentaires si le processus génère des lignes partielles, celles-ci doivent être mises en mémoire tampon.

Si cette solution plus générale est nécessaire, j'écrirais ceci en utilisant expect car elle prend déjà bien en charge la gestion de la correspondance de modèles sur plusieurs flux d'entrée. Cependant, ce n'est pas une solution bash/zsh.


Dans ce cas particulier, j'utiliserais perl :

printf '%s\n' foo bar | perl -Mopen=locale -lpe '$_ .= " " . reverse$_'
foo oof
bar rab

Que vous pourriez étendre pour travailler également avec des clusters de graphèmes :

$ printf '%s\n' $'complique\u301' |
    perl -Mopen=locale -lpe '$_ .= " " . join "", reverse/\X/g'
compliqué éuqilpmoc

Ou zsh :

while IFS= read -r line; do
  print -r -- $line ${(j::)${(s::Oa)line}}
done

Bien que j'éviterais d'utiliser while read boucles pour traiter du texte, même en zsh (même si dans ce cas particulier, ce n'est pas si mal car seules les commandes intégrées sont utilisées).

Dans le cas général, l'utilisation de fichiers temporaires est probablement la meilleure approche. Avec zsh , vous pouvez le faire avec :

(){paste -d ' ' $1 <(rev <$1)} =(print -l foo bar)

(où =(...) se charge de créer et de nettoyer le fichier temporaire).

Le remplacer par des tuyaux et une forme de tee ing est une recette pour l'impasse dans le cas général. Consultez ces questions similaires pour certaines approches et des détails sur les situations de blocage :

  • Diviser une entrée pour différentes commandes et combiner le résultat
  • tee + cat :utiliser une sortie plusieurs fois puis concaténer les résultats

Linux
  1. Utilitaire de ligne de commande pour récupérer le mot de passe, qui n'a pas d'écho en retour ?

  2. Itérer sur chaque ligne de la sortie ls -l

  3. Obtenir la première ligne de la sortie d'une commande shell

  4. Bash si sur une seule ligne

  5. Comment lire la colonne IDLE dans la sortie de la commande Linux 'w' ?

Lolcat - Un outil de ligne de commande pour produire un arc-en-ciel de couleurs dans un terminal Linux

Commande de lecture bash

Commande Diff sous Linux

Prettyping - Rendre la sortie de la commande Ping plus jolie et plus facile à lire

Comment lire la sortie et les utilisations de la commande Linux Top

Comment lire les arguments de ligne de commande dans les scripts shell ?