作者 主題: 請教在Bash下有沒有工具可以做到像getc的工具  (閱讀 11589 次)

0 會員 與 1 訪客 正在閱讀本文。

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
正在嘗試寫一些有用的 Bash Shell 但除了用 read 指令外
若要不按Enter就得到按鍵內容,有什麼語法可以達到目的!

或者非要改用Perl來寫

duncanlo

  • SA 苦力組
  • 俺是博士!
  • *****
  • 文章數: 7312
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #1 於: 2002-06-05 16:24 »
我知道C可以,
而且學生的作業就有了...

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #2 於: 2002-06-05 22:50 »
謝謝duncanlo

下午去查Perl,直譯式Perl下的getc也一樣,書上寫了一個代用例,
透過/dev/stty的特殊作法,可惜沒有多作解釋。真的沒有工具可以用嗎?

用C語言?在Linux還不知要從何開始哩......更何況連 bash, php,
MySQL, Perl都還不透澈,真的有點好高騖遠!如果子程序的變數不能回傳給父程序。
光用c寫個小工具也一樣不行,dos那套做法不管用了。

duncanlo

  • SA 苦力組
  • 俺是博士!
  • *****
  • 文章數: 7312
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #3 於: 2002-06-05 23:04 »
再問一次,你是要抓User按的鍵嗎?

我看看我學生時代的作業可不可以在Linux上用!

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #4 於: 2002-06-06 09:37 »
我是想做出類似dos下的簡單選單

while
[.....]
echo "1. ....               # redraw the menu
echo "2. ....
....
echo "enter your chioce....:"
read press                # read user's enter
do
    case $press
    1)
       程序一
     ;;
    2)
       程序二
     ;;
     ......
     ......
    esac
done

可惜一定要多按下Enter才能回應,如果不用按Enter就能立即回應似乎會順暢一點

duncanlo

  • SA 苦力組
  • 俺是博士!
  • *****
  • 文章數: 7312
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #5 於: 2002-06-06 10:05 »
接enter才能確認吧!
你這東東用shell寫就可以了...

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #6 於: 2002-06-06 10:36 »
所以說是Shell 梆死了!所有的工具選單都不能設快鍵直接啟動囉?
或者有任何取得快鍵的方法,就像在vi下設Macro一樣。
或者有什麼方法可以直接從裝置取得事件?

jeffer

  • 懷疑的國中生
  • **
  • 文章數: 83
    • 檢視個人資料
shell 的 按一個鍵,就執行的寫法! (getc)
« 回覆 #7 於: 2002-06-06 11:19 »
這是我從網上找到的解法, 在 REDHAT 7.2 上跑沒有問題...

getc()
{
  stty raw
  eval $1='`dd bs=1 count=1 2>/dev/null`'
  stty cooked
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans
echo "bye !"

kenny

  • 訪客
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #8 於: 2002-06-06 11:36 »
記得一個月前在新聞組上就有人問過類似的問題。雖然我對 programing 不在行﹐但我有一個‘不良習慣’--- 貪心﹗發現別人的好東西﹐都後先抓下來再說。剛纔翻了一下﹐找到如下這段﹕

---------

"小州" <kenduest.bbs@bbs.sayya.org> 撰寫於郵件 news:40FeJR$6yN@bbs.sayya.org...
> ※ 引述《bm2fun.bbs@bbs.ntu.edu.tw (The Magic Word is D3)》之銘言:
> > 剛剛在幫朋友改一個shell script,就是那種標準用
> > read讀入字串然後作判斷的選單,突然想到用者種方式每次都要按
> > Enter後才能執行選項,而shell script是否能像C語言的getche()函數一樣直接
> > 抓一個鍵後不用按Enter就執行選項呢?
>
>   但是 getch、getche 不是 ansi c 的 function ....
>
>   剛剛用 google 找到一篇文章的內容有提到方式。
>
>   #!/bin/sh
>
>   echo "Enter a keystroke"
>   oldstty=`stty -g`
>   stty -icanon -echo min 1 time 0
>   key=`dd bs=4 count=1 <&0 2>/dev/null`
>   stty $oldstty
>   echo "key is" $key

---------


至於 bash 中的 read ﹐只所以要等 CR 字符﹐是因為 read 可以讀入多個字母做變數值﹐也能一次讀入多個變數值的緣故﹐例如﹕

echo -n "what is your full name: "
read FName LName
echo "Your fistname is $FNanem, and your lastname is $LName."

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #9 於: 2002-06-06 15:24 »
謝謝netman大哥及jeffer兄的解答:

實做後發現有點小問題
getc()
{
stty raw
eval $1='`dd bs=1 count=1 2>/dev/null`'
stty cooked
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans
echo "bye !"
無法關閉輸入鍵的回應
輸出如下:
#press a key
gthis is you type:
g
bye !

經過一番測試修正如下:
getc()
{
stty raw -echo
eval $1=`dd bs=1 count=1 2>/dev/null`
stty cooked echo
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans
echo "bye!"
大致正常了,但是如果按下的是兩碼的功能鍵還是有Bug要處理

> #!/bin/sh
>
> echo "Enter a keystroke"
> oldstty=`stty -g`
> stty -icanon -echo min 1 time 0
> key=`dd bs=4 count=1 <&0 2>/dev/null`
> stty $oldstty
> echo "key is" $key

小州兄這段程式則避開了這個問題
只是執行後所有KEYIN均不顯示了
只好綜合兩支程式

getc()
{
oldstty=`stty -g`
stty raw -echo min 1 time 0
eval $1=`dd bs=4 count=1 <&0 2>/dev/null`
stty $oldstty
stty cooked echo
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans
echo "bye!"

再研究如何取得功能鍵碼嚕 :P

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
請教在Bash下有沒有工具可以做到像getc的工具
« 回覆 #10 於: 2002-06-06 20:17 »
getc()
{
oldstty=`stty -g`
stty raw -echo # min 1 time 0 只有-icanon 狀況下有用。
eval $1=`dd bs=4 count=1 <&0 2>/dev/null` # #<&0是要停止來自檔案的輸入嗎?bs=5因為f7的回應為5碼會造成錯誤
stty $oldstty
stty cooked echo } 試過可以刪除
echo "press a key"
getc ans
echo "this is you type:"
echo $ans
echo "bye!"

改成下面的樣子,連功能鍵都可以識別了
getc()
{
oldstty=`stty -g`
stty raw -echo
eval $1=`dd bs=5 count=1  2>/dev/null`  
stty $oldstty
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans '+' ${ans#?}
echo "bye!"

但ctrl-系列仍然管不到

jeffer

  • 懷疑的國中生
  • **
  • 文章數: 83
    • 檢視個人資料
愈來愈遠了 ... 讓我們用正規的 read 來做 getc
« 回覆 #11 於: 2002-06-06 21:49 »
用這個方法應該比較正規
詳情請看 man bash 之 read

ans=""
echo -n "type key:<"
read -s -n 1 ans
echo $ans ">"
ans=""
read -s -n 1 ans
echo "<" $ans ">"
ans=""
read -n 5 -t 1 ans      # 用這個可能還可以寫出動態的 shell
echo "<" $ans ">"

  • 實習板主
  • 活潑的大學生
  • ***
  • 文章數: 270
    • 檢視個人資料
這就是只看舊書的缺點
« 回覆 #12 於: 2002-06-07 00:12 »
好訝異read有這些參數可用,看2nd Edition Linux in a nutshell原文舊書
(Feb 1999)真的查不到說…… 因為Linux的向下相容性,看天瓏打折
就買來看,反正是比自己列印man檔划算說。沒想到馬上就有查不到的東西。
更別說中文的指令辭典及Linux入門書介紹的內容。真的是找錯地方了! :(
-----------------------------------------------------------------------------
還是找男人比較有用   :lol:  

jeffer兄,謝謝啦!真的獲益匪淺。用這方法 ` \ | 三個跳脫字符就不會引起程序錯誤

仔細再看一遍:若用之前的寫法
eval $1='`dd bs=1 count=1 2>/dev/null`' #紅字部份不省略,\ ` |就不會造成錯誤跳出程序

比較傷腦筋的還是如何比對這些那些不易正常輸入的字符。c-A  Esc Backspace...

k1951223

  • 懷疑的國中生
  • **
  • 文章數: 58
    • 檢視個人資料
[問題]有關通用型的選單
« 回覆 #13 於: 2004-10-28 19:08 »
各位學長
   有沒有較方便使用的選單程式
就是只要改參數檔就可以更改選單內容的
我在網路上找到二個程式範例
有一個還有光棒移動的選單
但是寫的不夠完整沒有辦法直接執行
可否請各位學長幫忙測試看看

在Unix系統下用shell製作通用界面
http://www.ddvip.net/os/scounix/index1/4.htm

menu是shell寫成的shell函數
http://bbs.chinaunix.net/forum/24/20040414/304106.html

wushihchieh

  • 可愛的小學生
  • *
  • 文章數: 1
    • 檢視個人資料
前面提的程式碼,摘錄如下:

getc()
{
oldstty=`stty -g`
stty raw -echo
eval $1=`dd bs=5 count=1  2>/dev/null`  
stty $oldstty
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans '+' ${ans#?}
echo "bye!"

似乎無法抓到Enter鍵!

我正在撰寫光棒選單的基本架構,目前已經完成99%
目前遭遇的問題是無法抓到Enter鍵,希望有高手能夠指點迷津!

晚一點會將寫好的script貼上。

#!/bin/bash

ColorRED=1
ColorGREEN=2
ColorYELLOW=3
ColorBLUE=4
ColorMAGENTA=5
ColorCYAN=6
ColorGRAY=7
ColorWHITE=8
ColorEnhanceWHITE=9
ColorBLACK=10

#顯示彩色文字需要四個參數,分別是前景色、背景色、樣式及文字
function ColorText()
{
   ForegroundColor="3""$1"
   BackgroundColor="4""$2"
   SetColor="\E[""$ForegroundColor;$BackgroundColor""m"
   SetStyle="\033[""$3""m"
   TextContent="$4"
   ResetAll="\033[0m"
   echo -e -n "$SetColor""$SetStyle""$TextContent""$ResetAll"
}

function Cursor()
{
   local   cursor_status

   cursor_status=$1
   case $cursor_status in
      off|OFF)
         echo -e "\033[?25l"
         ;;
      on|ON)
         echo -e "\033[?25h"
         ;;
      *)
         return 1
         ;;
   esac
}

function GotoXY()
{
   local   row
   local   col

   row=$1
   col=$2
   echo -e -n "\033[$row;$col""H""\033[0m"
}

function GetKey()
{
   oldstty=`stty -g`
   stty raw -echo
   eval $1=`dd bs=5 count=1  2>/dev/null`
   stty $oldstty
}

TotalItems=$(cat MenuItemName | wc -l)
Row_Of_Menu=5
Col_Of_Menu=5

clear
Cursor OFF

for ((ItemIndex=1; ItemIndex <= $TotalItems; ItemIndex++))
do
   ItemName[$ItemIndex]=$(sed -n "$ItemIndex""p" MenuItemName)
   ItemRow=$(expr $Row_Of_Menu + $ItemIndex)

   GotoXY $ItemRow $Col_Of_Menu
   ColorText $ColorWHITE $ColorBLUE  1 "$ItemIndex)   ${ItemName[$ItemIndex]}   ($ItemIndex"
done

CurrentIndex=1
while [ 1 ]
do

   GotoXY $(expr $Row_Of_Menu + $TotalItems + 2) $Col_Of_Menu; echo "Key Char  : " ${PressKey#?}
   GotoXY $(expr $Row_Of_Menu + $TotalItems + 3) $Col_Of_Menu; echo "Current   : " $CurrentIndex

   Row_Of_BAR=$(expr $Row_Of_Menu + $CurrentIndex)
   
   GotoXY $Row_Of_BAR $Col_Of_Menu
   ColorText $ColorWHITE $ColorRED  1 "$CurrentIndex)   ${ItemName[$CurrentIndex]}   ($CurrentIndex"
   
   GetKey PressKey
   
   GotoXY $Row_Of_BAR $Col_Of_Menu
   ColorText $ColorWHITE $ColorBLUE 1 "$CurrentIndex)   ${ItemName[$CurrentIndex]}   ($CurrentIndex"

   if [ "${PressKey#?}" == "[B" ]; then
      if [ $CurrentIndex == $TotalItems ]; then
         CurrentIndex=1
      else
         ((CurrentIndex++))
      fi
   fi
   if [ "${PressKey#?}" == "[A" ]; then
      if [ $CurrentIndex == 1 ]; then
         CurrentIndex=$TotalItems
      else
         ((CurrentIndex--))
      fi
   fi
   if [ "$PressKey" == "0" ]; then
      GotoXY $Row_Of_BAR $Col_Of_Menu
      ColorText $ColorWHITE $ColorRED  1 "$CurrentIndex)   ${ItemName[$CurrentIndex]}   ($CurrentIndex"
      GotoXY $(expr $Row_Of_Menu + $TotalItems + 4) $Col_Of_Menu
      echo "Your selection is" ${ItemName[$CurrentIndex]}
      Cursor ON
      break
   fi
done

MenuItemName的內容如下:

MenuItem #1
MenuItem #2
MenuItem #3
MenuItem #4
MenuItem #5
MenuItem #6
MenuItem #7
MenuItem #8
MenuItem #9
« 上次編輯: 2010-01-08 17:15 由 wushihchieh »