Board logo

标题: Shell Curses 函数库(2) [打印本页]

作者: look_w    时间: 2018-6-14 17:51     标题: Shell Curses 函数库(2)

示例由于篇幅限制,本文没有提供这些函数的实际代码。有关下载信息,请参阅部分。
人们已使用 Shell Curses 创建了许多工具集,以便为安装系统、菜单程序、数据输入应用程序、数据库等等提供前端界面。下面将提供一些说明各个函数用法的示例。
在编写 Shell 脚本时,必须首先做出的决定之一为是否要使用某个函数库,或者是否要包括某个文件作为包含所有必需函数的“点”脚本。Shell Curses 可以通过任一种机制进行利用,具体使用哪一种机制将由 Shell 程序员做出决定。下面的示例将把 Shell Curses 的使用表示为函数库,因为对本讨论来说,这是最高效的机制。作为函数库,每个函数应该在某个目录中作为与函数具有相同名称的单独文件存在。在这些示例中,用于 Shell Curses 函数库的目录为 /usr/local/function/shellcurses。这些示例还使用 Korn Shell 93 作为脚本解释器,这是在每个脚本开头的 shebang 行进行定义的 (#!/usr/bin/ksh93)。
在 IBM® AIX® 下面使用 Shell Curses 函数库的一个问题在于,AIX 已经提供了名为 clear 和 refresh 的已编译库,这些库将与具有相同名称的 Shell 函数产生混淆。要解决此问题,应该将 clear、refresh 和 initscr 函数全都复制到单个文件中名为 initscr 的函数库中。这可以确保在调用 initscr 函数时,将同时初始化 clear 和 refresh 的 Shell Curses 函数,从而避免与 AIX 二进制命令 clear 和 refresh 产生混淆。
此示例使用 Shell Curses 函数来清屏;将光标移动到第 10 行,第 25 列;并在该位置打印单词 Hello World!。然后将光标移动到第 23 行,第 1 列。请注意对 refresh 函数的调用。这是实际将命令发送到屏幕以进行显示的函数。
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/ksh93
FPATH="/usr/local/functions/shellcurses"

initscr
clear
move 10 25
addstr "Example 1: Hello World!"
move 23 1
refresh
endwin

exit 0




下一个示例与前一个示例相同,只不过是使用单个 mvaddstr 函数,而不是使用两个函数,即使用 move 然后再使用 addstr:
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/ksh93
FPATH="/usr/local/functions/shellcurses"

initscr
clear
mvaddstr 10 25 "Example 2: Hello World!"
move 23 1
refresh
endwin

exit 0




第三个示例提示用户输入一些数据,然后在屏幕下方的某个位置显示该数据。请注意,提示包含在一个 Shell 变量中,提示中的字符数量用于确定要在屏幕上放置光标的位置,以便用户输入数据。还要注意,refresh 函数在 getstr 函数之前调用,以便在提示用户输入数据之前,将命令刷新到屏幕:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/ksh93
FPATH="/usr/local/functions/shellcurses"

initscr
clear

PROMPT="Example 3: Enter some data...:"
LEN="${#PROMPT}"
(( COL = LEN + 2 + 1 ))

mvaddstr 10 2 "${PROMPT}"
move 10 ${COL}
refresh

ANS=$( getstr )
mvaddstr 15 2 "Here is the data you entered.: ${ANS}"
move 23 1
refresh

endwin

exit 0




第四个示例提供一个完整的菜单系统,并具有标题和针对无效选择的错误检查。此示例还在做出选择并显示用户的选择之后重新绘制屏幕。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/ksh93
FPATH="/usr/local/functions/shellcurses"
SCRWID="80"

initscr
clear

#### Display a screen header, centered on the screen
HEADER="Shell Curses Example 4"
HDRWID="${#HEADER}"
(( HDRBEGIN = ( SCRWID - HDRWID ) / 2 ))
mvaddstr 1 ${HDRBEGIN} "${HEADER}"

MENU[0]="First Menu Line"
MENU[1]="Second Menu Line"
MENU[2]="Third Menu Line"
MENU[3]="Fourth Menu Line"
MENU[4]="Fifth Menu Line"
ITEMCNT="${#MENU[@]}"
MENUWID="${#MENU[0]}"

#### Determine the maximum length of the longest menu item
for MENULINE in "${MENU[@]}"
do
  (( ${#MENULINE} > MENUWID )) && (( MENUWID = ${#MENULINE} + 4 ))
done

#### Display the numbered menu item, centered on the screen
(( COL = ( SCRWID - MENUWID ) / 2 ))
NBR="0"
for MENULINE in "${MENU[@]}"
do
  mvaddstr $(( ++NBR + 4 )) ${COL} "${NBR} = ${MENULINE}"
done

#### Prompt the user for a selection
mvaddstr 22 2 "Enter the number of your selection: "
mvaddstr 23 2 "( 0 = Exit )"

#### Read the users selection from the screen
ANSWER="99"
while [[ "_${ANSWER}" != _[0-9] ]] ||
      (( ANSWER < 1 )) ||
      (( ANSWER > ITEMCNT ))
do
  [[ "_${ANSWER}" == _0 ]] && exit 0
  mvclrtoeol 22 40
  refresh
  ANSWER="$( getstr )"
done

#### Display the item number selected by the user
clear
mvaddstr 1 ${HDRBEGIN} "${HEADER}"
mvaddstr 4 2 "You selected menu item number ${ANSWER}"
move 23 1
refresh

endwin

exit ${ANSWER}




第五个示例提供了一个带有错误检查功能的完整多行数据输入系统。此示例利用了动态确定的屏幕宽度和高度,它还使用了反转的视频屏幕属性来强调屏幕上显示的错误消息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/ksh93
FPATH="/usr/local/functions/shellcurses"

initscr
SCRWID="${MAX_COLS}"
SCRLEN="${MAX_LINES}"
clear

#### Display a two line header, centered on the screen
HEADER1="Shell Curses Example 5"
HEADER2="Data Entry Screen"
mvaddstr 1 $(( ( SCRWID - ${#HEADER1} ) / 2 )) "${HEADER1}"
mvaddstr 2 $(( ( SCRWID - ${#HEADER2} ) / 2 )) "${HEADER2}"

#### Define the user entry prompts
DOTS="........................................"
PRMPT[1]="Enter an existing directory name"
PRMPT[2]="Enter an existing regular file name"
PRMPT[3]="Enter an alpha-numeric value"
PRMPT[4]="Enter a numeric value"
PRMPT[5]="Enter an executable file name"
PCNT="${#PRMPT[@]}"

#### Display the numbered data entry prompt with trailing dots
for IDX in "${!PRMPT[@]}"
do
    (( DOTWID = ( SCRWID / 2 ) - ( ${#PRMPT[IDX]} + 4 ) ))
    PRMPT[IDX]="${PRMPT[IDX]}${DOTS:0{DOTWID}}"
    mvaddstr $(( IDX + 4 )) 2 "${IDX}: ${PRMPT[IDX]}...:"
done
DATACOL="$(( ${#PRMPT[1]} + 10 ))"

#### Prompt the user for a selection
mvaddstr $(( SCRLEN - 3 )) 2 "Select a line number to enter data:"

#### Read the users data line number selection from the screen
while :
do
#### Read the line number entered by the user
    mvclrtoeol $(( SCRLEN - 3 )) 40
    refresh
    ANS="$( getstr )"

#### clear the status line and re-display the default status message
    mvclrtoeol $(( SCRLEN - 2 )) 2
    mvaddstr $(( SCRLEN - 2 )) 2 "( 0 = Exit )"

#### Validate the user entered line number, if invalid go back and ask again
    [[ "_${ANS}" == "_0" ]] && exit 0
    if [[ "_${ANS}" != _+([[:digit:]]) ]] || (( ANS < 1 )) || (( ANS > PCNT ))
    then
        continue
    fi

#### Read the line data from the user entry
    mvclrtoeol $(( ANS + 4 )) ${DATACOL}
    refresh
    DATA[${ANS}]="$( getstr )"

    mvclrtoeol $(( SCRLEN - 2 )) 2
    attrset rev

#### Check the validity of the line 1 data as entered by the user
    if (( ANS == 1 )) && [[ ! -d "${DATA[${ANS}]}" ]]
    then
        mvclrtoeol $(( ANS + 4 )) ${DATACOL}
        mvaddstr $(( SCRLEN - 2 )) 2 "ERROR: Invalid Directory Name"
    fi

#### Check the validity of the line 2 data as entered by the user
    if (( ANS == 2 )) && [[ ! -f "${DATA[${ANS}]}" ]]
    then
        mvclrtoeol $(( ANS + 4 )) ${DATACOL}
        mvaddstr $(( SCRLEN - 2 )) 2 "ERROR: Invalid Regular File Name"
    fi

#### Check the validity of the line 3 data as entered by the user
    if (( ANS == 3 )) && [[ "_${DATA[${ANS}]}" != _+([[:alnum:]]) ]]
    then
        mvclrtoeol $(( ANS + 4 )) ${DATACOL}
        mvaddstr $(( SCRLEN - 2 )) 2 "ERROR: Invalid Alpha-Numeric Value"
    fi

#### Check the validity of the line 4 data as entered by the user
    if (( ANS == 4 )) && [[ "_${DATA[${ANS}]}" != _+([[:digit:]]) ]]
    then
        mvclrtoeol $(( ANS + 4 )) ${DATACOL}
        mvaddstr $(( SCRLEN - 2 )) 2 "ERROR: Invalid Numeric Value"
    fi

#### Check the validity of the line 5 data as entered by the user
    if (( ANS == 5 )) && [[ ! -x "${DATA[${ANS}]}" ]]
    then
        mvclrtoeol $(( ANS + 4 )) ${DATACOL}
        mvaddstr $(( SCRLEN - 2 )) 2 "ERROR: File is not executable or
         does not exist"
    fi
    attroff
    refresh

done

endwin

exit ${ANS}




这些示例代表了 Shell Curses 函数库的应用和用法的一小部分。 下面存在一个基于 Shell Curses 的标准化菜单和数据输入系统。
该菜单系统为 Shell 程序员提供了创建多级菜单系统和多屏数据输入程序的能力,这些多级菜单系统和多屏数据输入程序可与广泛的程序和数据库连接。如果没有指定后端程序或数据库,则使用内置的数据库系统来存储用户指定的信息。为了演示这些功能,下面将提供一个演示程序。French Menus 也充分(如果不是全部的话)利用了 Shell Curses 库中的函数,并且是设计和实现其他应用程序时的理想参考工具。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0