web-dev-qa-db-fra.com

Sortie du tuyau vers la fonction bash

J'ai une fonction aussi simple dans un script bash et je voudrais y diriger stdout en entrée.

jc_hms(){
  printf "$1"
}

Je voudrais l'utiliser de cette manière.

var=`echo "teststring" | jc_hms`

Bien sûr, j'ai utilisé les fonctions redondantes echo et printf pour simplifier la question, mais vous avez compris. En ce moment, j'obtiens une erreur "introuvable", ce qui, je suppose, signifie que la délimitation de mes paramètres est incorrecte (la partie "$ 1"). Aucune suggestion?

À l'origine, la fonction jc_hms était utilisée comme ceci:

echo `jc_hms "teststring"` > //dev/tts/0

mais je voudrais d'abord stocker les résultats dans une variable pour un traitement ultérieur, avant de les envoyer au port série.

EDIT: Donc, pour clarifier, je n'essaie PAS d'imprimer des choses sur le port série, je voudrais interfacer avec mes fonctions bash si le "|" caractère de pipe, et je me demande si cela est possible.

EDIT: Très bien, voici la fonction complète.

jc_hms(){
  hr=$(($1 / 3600))
  min=$(($1 / 60))
  sec=$(($1 % 60))

  printf "$hs:%02d:%02d" $min $sec
}

J'utilise la fonction pour former une chaîne qui vient cette ligne de code

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring

Où $ songtime est une chaîne exprimée en "playtime totaltime" délimitée par un espace.

J'aimerais pouvoir le faire en une seule ligne et le canaliser après le awk

printstring=`echo $songtime | awk '{print S1 }' | jc_hms`

ainsi.

63
jliu83

Pour répondre à votre question réelle, lorsqu'une fonction Shell se trouve sur l'extrémité réceptrice d'un canal, l'entrée standard est lue par la première commande exécutée à l'intérieur de la fonction. Puisque printf est la première et la seule commande de votre fonction, l'entrée standard est ignorée. Il existe plusieurs façons de contourner cela, notamment en utilisant le read intégré pour lire l'entrée standard dans une variable qui peut être passée à printf:

jc_hms () {
    read foo
    hr=$(($foo / 3600))
    min=$(($foo / 60))
    sec=$(($foo % 60))
    printf "%d:%02d:%02d" "$hr" "$min" "$sec"
}

Cependant, puisque votre besoin d'un pipeline semble dépendre de votre besoin perçu d'utiliser awk, permettez-moi de suggérer l'alternative suivante:

printstring=$( jc_hms $songtime )

Étant donné que songtime consiste en une paire de nombres séparés par des espaces, le shell effectue un fractionnement de Word sur la valeur de songtime et jc_hms voit deux paramètres distincts. Cela ne nécessite aucun changement dans la définition de jc_hms, et pas besoin de rien y faire via une entrée standard.

Si vous avez encore une raison différente de jc_hms pour lire l'entrée standard, veuillez nous le faire savoir.

57
chepner

Vous ne pouvez pas diriger des éléments directement vers une fonction bash comme celle-ci, mais vous pouvez utiliser read pour les extraire à la place:

jc_hms(){
  while read data; do
      printf "%s" "$data"
  done
}

devrait être ce que tu veux

46
moopet

1) Je sais que c'est un assez vieux post

2) J'aime la plupart des réponses ici

Cependant, j'ai trouvé ce message parce que j'avais besoin de quelque chose de similaire. Alors que tout le monde convient que stdin est ce qui doit être utilisé, ce qui manque ici, c'est l'utilisation réelle du fichier/dev/stdin.

L'utilisation de la fonction intégrée de lecture force cette fonction à être utilisée avec une entrée canalisée, de sorte qu'elle ne peut plus être utilisée de manière typique. Je pense que l'utilisation de/dev/stdin est un moyen supérieur de résoudre ce problème, j'ai donc voulu ajouter mes 2 cents pour être complet.

Ma solution:

jc_hms() { 
  declare -i i=${1:-$(</dev/stdin)};
  declare hr=$(($i/3600)) min=$(($i/60%60)) sec=$(($i%60));
  printf "%02d:%02d:%02d\n" $hr $min $sec;
}

En action:

user@hostname:pwd$ jc_hms 7800
02:10:00
user@hostname:pwd$ echo 7800 | jc_hms 
02:10:00

J'espère que cela peut aider quelqu'un.

Bon piratage!

32
user.friendly

Ou, vous pouvez également le faire de manière simple.

jc_hms() {
    cat
}

Bien que toutes les réponses à ce jour n'aient pas tenu compte du fait que ce n'était pas ce que voulait OP (il a déclaré que la fonction était simplifiée)

15
Jo So

J'aime la réponse de user.friendly en utilisant la syntaxe de substitution non définie conditionnelle Bash intégrée. Voici un léger Tweak pour rendre sa réponse plus générique, comme pour les cas avec un nombre de paramètres indéterminé:

function myfunc() {
    declare MY_INPUT=${*:-$(</dev/stdin)}
    for PARAM in $MY_INPUT; do
        # do what needs to be done on each input value
    done
}
10
Der Schley

Hmmmm ....

songplaytime=`echo $songtime | awk '{print S1 }'`
printstring="`jc_hms $songplaytime`"  #store resulting string in printstring

si vous appelez quand même awk, pourquoi ne pas l'utiliser?

printstring=`TZ=UTC gawk -vT=$songplaytime 'BEGIN{print strftime("%T",T)}'`

Je suppose que vous utilisez Awk de Gnu, qui est le meilleur et aussi gratuit; cela fonctionnera dans les distributions Linux courantes qui n'utilisent pas nécessairement le gawk le plus récent. Les versions les plus récentes de gawk vous permettront de spécifier UTC comme troisième paramètre de la fonction strftime ().

1
Medievalist