stdinから変数に複数行の入力を読み込む方法と、shell(sh、bash)で出力する方法
質問
やりたいことは次のとおりです:
-
stdin
から変数A
への複数行入力の読み取り
-
\n
でさまざまな操作を行う
- パイプ
\r
区切り記号(\t
、read
、cat
など)を別のコマンドに失わずに
現在の問題は、改行で読み取りを停止するため、<=>コマンドで読み取ることができないことです。
次のように、<=>でstdinを読むことができます:
my_var=`cat /dev/stdin`
、しかし、それを印刷する方法がわかりません。そのため、改行、タブ、およびその他の区切り文字はまだそこにあります。
私のサンプルスクリプトは次のようになります。
#!/usr/local/bin/bash
A=`cat /dev/stdin`
if [ ${#A} -eq 0 ]; then
exit 0
else
cat ${A} | /usr/local/sbin/nextcommand
fi
解決
これは私のために働いています:
myvar=`cat`
echo "$myvar"
$myvar
を囲む引用符は重要です。
他のヒント
Bashには、別の方法があります。 man bash
言及:
コマンド置換
$(cat file)
は、同等の高速な$(< file)
に置き換えることができます。
$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test
tee が仕事をします
#!/bin/bash
myVar=$(tee)
はい、それは私にも有効です。ありがとう。
myvar=`cat`
は次と同じ
myvar=`cat /dev/stdin`
そうですね。 bash
manページから:
二重引用符で文字を囲む すべてのリテラル値を保持します 引用符内の文字、 $、 `、\を除き、履歴展開が 有効、!文字$および ` 二重引用符内で特別な意味を保持します。
出力の最後で末尾の改行を保持することに関心がある場合は、これを使用します:
myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"
これは、こちらのトリックを使用しています。
[更新済み]
パイプに何もない場合、この割り当ては無期限にハングします...
var="$(< /dev/stdin)"
最初の文字にタイムアウトread
を行うことで、これを防ぐことができます。タイムアウトになると、戻りコードは128を超え、STDINパイプ(別名/dev/stdin
)が空であることがわかります。
それ以外の場合は、STDINの残りの部分を取得します...
-
IFS
コマンドに対してのみ-r
をNULLに設定 -
-d ''
でエスケープをオフにする
-
var="$(command ...)"
を使用して読み取りの区切り文字を削除します。 - そして最後に、最初に得たキャラクターにそれを追加します
したがって...
__=""
_stdin=""
read -N1 -t1 __ && {
(( $? <= 128 )) && {
IFS= read -rd '' _stdin
_stdin="$__$_stdin"
}
}
この手法は、設計上、後続の改行を常に削除する$()
コマンド置換の使用を回避します。
コマンド置換が優先される場合、末尾の改行を保持するために、1つ以上の区切り文字を$(parens)
内の出力に追加し、外部でそれらを削除できます。
たとえば、(最初のコマンドでは${braces}
に、2番目のコマンドでは<=>に注意) ...
_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"