Comment lire une entrée multiligne de stdin en variable et comment en imprimer une en shell (sh, bash)?

StackOverflow https://stackoverflow.com/questions/212965

  •  03-07-2019
  •  | 
  •  

Question

Ce que je veux faire est le suivant:

  1. lit plusieurs lignes à partir de stdin dans la variable A
  2. effectuer diverses opérations sur \n
  3. canaliser \r sans perdre les symboles de délimiteur (\t, read, cat, etc.) vers une autre commande

Le problème actuel est que je ne peux pas le lire avec la commande <=> car il arrête la lecture à la nouvelle ligne.

Je peux lire stdin avec <=>, comme ceci:

my_var=`cat /dev/stdin`

, mais je ne sais pas comment l’imprimer. De sorte que la nouvelle ligne, l'onglet et d'autres délimiteurs soient toujours présents.

Mon exemple de script ressemble à ceci:

#!/usr/local/bin/bash

A=`cat /dev/stdin`

if [ ${#A} -eq 0 ]; then
        exit 0
else
        cat ${A} | /usr/local/sbin/nextcommand
fi
Était-ce utile?

La solution

Cela fonctionne pour moi:

myvar=`cat`

echo "$myvar"

Les guillemets autour de $myvar sont importants.

Autres conseils

Dans Bash, il existe un autre moyen: man bash mentionne:

  

La substitution de commande $(cat file) peut être remplacée par l'équivalent mais plus rapidement $(< file).

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test

tee fait le travail

#!/bin/bash
myVar=$(tee)

Oui, ça marche aussi pour moi. Merci.

myvar=`cat`

est identique à

myvar=`cat /dev/stdin`

Bien oui. A partir de la bash page de manuel:

  

Caractères entre guillemets   préserve la valeur littérale de tous   caractères entre guillemets,   à l'exception de $, `, \ et lorsque l'extension de l'historique est   activée, !. Les personnages $ et `   conservez leur signification particulière entre guillemets doubles.

Si vous vous souciez de conserver les retours à la fin à la fin de la sortie, utilisez ceci:

myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"

Ceci utilise le truc de ici .

[mise à jour]

Cette affectation sera suspendue indéfiniment s'il n'y a rien dans le tuyau ...

var="$(< /dev/stdin)"

Nous pouvons toutefois éviter cela en faisant un délai d'attente read pour le premier caractère. S'il expire, le code de retour sera supérieur à 128 et nous saurons que le canal STDIN (a.k.a /dev/stdin) est vide.

Sinon, nous obtenons le reste de STDIN par ...

  • définir IFS sur NULL pour la -r commande
  • désactiver les sorties avec -d ''
  • élimination du délimiteur de lecture avec var="$(command ...)".
  • et enfin, en ajoutant cela au personnage que nous avons obtenu initialement

Ainsi ...

__=""
_stdin=""

read -N1 -t1 __  && {
  (( $? <= 128 ))  && {
    IFS= read -rd '' _stdin
    _stdin="$__$_stdin"
  }
}

Cette technique évite d'utiliser $() la substitution de commande qui, de par sa conception, supprime toujours les retours à la ligne.

Si vous préférez remplacer les commandes, vous pouvez ajouter un ou plusieurs caractères de délimitation à la sortie située à l'intérieur de $(parens) pour les conserver à la fin de la ligne, puis les supprimer à l'extérieur.

Par exemple (remarque ${braces} dans la première commande et <=> en seconde) ...

_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top