web-dev-qa-db-ja.com

bash関数へのパイプ出力

Bashスクリプトには単純な関数があり、stdoutを入力としてパイプしたいと思います。

jc_hms(){
  printf "$1"
}

このように使いたいです。

var=`echo "teststring" | jc_hms`

もちろん、冗長な関数echoとprintfを使用して質問を簡素化しましたが、アイデアは得られます。現在、「not found」エラーが表示されます。これは、パラメータの区切りが間違っていることを意味します(「$ 1」の部分)。助言がありますか?

当初、jc_hms関数は次のように使用されていました。

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

ただし、結果をシリアルポートに送信する前に、最初の処理のために変数に保存したいと思います。

編集:だから、明確にするために、シリアルポートに物を印刷しようとはしていません。「|」があれば、bash関数にインターフェイスしたいと思いますパイプ文字、これが可能かどうか疑問に思っています。

編集:さて、ここに完全な機能があります。

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

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

このコード行に来る文字列を形成するために関数を使用しています

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

$ songtimeは、スペースで区切られた「playtime totaltime」として表される文字列です。

これを1行で行い、awkの後にパイプすることができればいいのに

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

そのようです。

63
jliu83

実際の質問に答えるために、シェル関数がパイプの受信側にある場合、関数内で実行される最初のコマンドによって標準入力が読み取られます。 printfは関数の最初で唯一のコマンドであるため、標準入力は無視されます。 readビルトインを使用して、標準入力をprintfに渡すことができる変数に読み込むなど、いくつかの方法があります。

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

ただし、パイプラインの必要性はawkを使用する必要性に依存しているように思われるため、次の代替案を提案させてください。

printstring=$( jc_hms $songtime )

songtimeはスペースで区切られた数字のペアで構成されているため、シェルはsongtimeの値に対してワード分割を実行し、jc_hmsは2つの別個のパラメーターを認識します。これには、jc_hmsの定義を変更する必要がなく、標準入力を介して何かをパイプする必要もありません。

jc_hmsが標準入力を読み取る別の理由がまだある場合は、お知らせください。

57
chepner

そのようなbash関数に直接パイプすることはできませんが、代わりにreadを使用してプルすることができます:

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

あなたが望むものでなければなりません

46
moopet

1)私はこれがかなり古い投稿であることを知っています

2)私はここの答えのほとんどが好きです

しかし、私は似たような何かが必要だったので、この投稿を見つけました。誰もがstdinを使用する必要があることに同意しますが、ここでの答えが欠けているのは、/ dev/stdinファイルの実際の使用法です。

Readビルトインを使用すると、この関数はパイプ入力で強制的に使用されるため、通常の方法では使用できなくなります。/dev/stdinを利用することは、この問題を解決する優れた方法だと思うので、完全を期すために2セントを追加したいと考えました。

私の解決策:

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;
}

動作中:

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

これが誰かの助けになることを願っています。

ハッピーハッキング!

32
user.friendly

または、簡単な方法で行うこともできます。

jc_hms() {
    cat
}

これまでのすべての答えは、これがOPが望んでいたものではないという事実を無視しましたが(彼は機能が簡素化されていると述べました)

15
Jo So

私はBash組み込み条件付き未設定置換構文を使用したuser.friendlyの答えが好きです。不確定なパラメータカウントの場合など、答えをより一般的にするための微調整を次に示します。

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

うーん...

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

とにかくawkを呼び出している場合は、なぜそれを使用しないのですか?

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

私はあなたがGnuのAwkを使用していると仮定しています。これは最高のものであり、しかも無料です。これは、最新のgawkを必ずしも使用しない一般的なLinuxディストリビューションで機能します。 gawkの最新バージョンでは、strftime()関数の3番目のパラメーターとしてUTCを指定できます。

1
Medievalist