私はどんなシェルでも動作する結果を得るためにウェブを検索し、技術をテストするのに10時間を費やしました(#!/bin/sh
)。
read
BASHでは、キャッチする文字数を知り、区切り文字が見つかるとすぐに終了するので、比較的簡単です。
stty -icanon -echo; echo -en "\033[6n"; read -d R -n 12 ESCPOS; stty "$x_TERM"; \
ESCPOS=`echo "$ESCPOS" | tail -c +3`; echo "$ESCPOS"
すべてのシェルと互換性のあるshスクリプトバージョンを作成するには?
答え1
コピーした場所https://unix.stackexchange.com/a/88327
/bin/sh
POSIXを使用しているとしますsh
(Bourneシェルを使用できるSolaris 10以前では、代わりにそれを使用してください/usr/xpg4/bin/sh
)。
if [ -t 0 ] && [ -t 1 ]; then
old_settings=$(stty -g) || exit
stty -icanon -echo min 0 time 3 || exit
printf '\033[6n'
pos=$(dd count=1 2> /dev/null)
pos=${pos%R*}
pos=${pos##*\[}
x=${pos##*;} y=${pos%%;*}
stty "$old_settings"
fi
全体の応答が一度に最大0.3秒待機すると仮定します。これは一般的にターミナルエミュレータとptyデバイスに適用されますが、シリアルターミナルには必ずしもそうではありません。 8バイトを読むまで待つように(各バイト間最大0.3秒)変更できますが、min 8 time 3
答えが8バイトより短い場合は常に最小0.3秒かかり、答えがない場合は常に0.3秒かかるという欠点があります。 。
awk -F'[^0-9]+' -v RS=R '{print $3, $2; exit}'
で使用できますmin 1 time 0
。これは、他の実装(入力処理を開始する前に入力データでいっぱいのバッファを蓄積する必要がある)awk
と組み合わせて使用できます。mawk
結局、自分の答えのように、一度に1バイトずつ読み込むのが最も安定しています。応答を送信しないエンドポイントを説明するためにタイムアウトを追加する必要があるかもしれません。
答え2
メモ:
unlike the wrongly copied and continually upvoted answer provided
(points scoring?), the following script IS NON-BLOCKING, and does
not care what length returned input may be. IE it will work with
ANY screen size.
SHの使用はより複雑で、組み込みの拡張コマンドラインバージョンが見つかりませんでした。read
結局、STDINへの言及が見つかり、dd
結果は次のとおりです。内蔵SHバージョンは使用できますが、echo
許可されていません。echo -en
/bin/echo -en
printf
#!/bin/sh
x_TERM=`stty -g`
stty -icanon -echo
printf "\033[6n"
ESCPOS=""
X=""
I=0
while [ ! "$X" = "R" ]; do
X=`dd bs=1 count=1 2>/dev/null`
I=`expr $I + 1`
if [ $I -gt 2 -a ! "$X" = "R" ]; then
ESCPOS="$ESCPOS$X"
fi
done
stty "$x_TERM"
#echo "$ESCPOS"
CSRLIN=`echo "$ESCPOS" | cut -d \; -s -f 1`
POS=`echo "$ESCPOS" | cut -d \; -s -f 2`
echo "$CSRLIN"
#exit 0 <= dont use inline
私は2つの異なるスクリプトで同じコードを使用しています。 1つは出力用CSRLIN
で、もう1つは出力用ですPOS
。
編集する:. CSRLIN
このスクリプトを他のスクリプト(たとえば、シェルがインタラクティブモードにする必要があるため)で使用するには、インライン化する必要があります。
乾杯
ポール