Shell编程—处理用户输入

1命令行参数

1.1读取参数

bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的所有参数。这也包括shell所执行的脚本名称。位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推,直到第九个参数$9。

例子:计算阶乘

$ vim test1.sh
#!/bin/bash
# using one command line parameter
factorial=1
for (( number = 1; number <= $1 ; number++ ))
do
   factorial=$[ $factorial * $number ]
done
echo The factorial of $1 is $factorial

$ ./test1.sh 5
The factorial of 5 is 120

例子:参数是字符串的情况

$ cat test3.sh
#!/bin/bash
# testing string parameters
echo "Hello $1, glad to meet you."

$ ./test3.sh Rich
Hello Rich, glad to meet you.

如果脚本需要的命令行参数不止9个的话。可以在第9个变量之后,在变量数字周围加上花括号,比如${10}。

1.2读取脚本名

以用$0参数获取shell在命令行启动的脚本名。

$ cat test5.sh
#!/bin/bash
# Testing the $0 parameter
echo The zero parameter is set to: $0 

$bash test5.sh
The zero parameter is set to: test5.sh

但是这里存在一个潜在的问题。如果使用另一个命令来运行shell脚本,命令会和脚本名混在一起,出现在$0参数中。比如:

$ ./test5.sh
The zero parameter is set to: ./test5.sh
$ bash /home/Christine/test5.sh
The zero parameter is set to: /home/Christine/test5.sh

这个时候basename命令可以帮助我们,basename命令会返回不包含路径的脚本名。

$ cat test5b.sh
#!/bin/bash
# Using basename with the $0 parameter
name=$(basename $0)
echo echo The script name is: $name

$ bash /home/Christine/test5b.sh
The script name is: test5b.sh

$ ./test5b.sh
The script name is: test5b.sh

可以用这种方法来编写基于脚本名执行不同功能的脚本。这里有个简单的例子:

$ cat test6.sh
#!/bin/bash
name=$(basename $0)
#判断参数是否为空,如果为空的话(就是执行脚本时少带了参数),后面的脚本会报错
if [ -e  $1 ]
then
echo "\$1 is empty"
exit 1
elif [ -e $2 ]
then
echo "\$2 is empty"
exit 1
fi

if [ $name = "addem" ]
then
   total=$[ $1 + $2 ]
elif [ $name = "multem" ]
then
   total=$[ $1 * $2 ]
fi
echo The calculated value is $total 

开始测试:
$ cp test6.sh addem
$ chmod u+x addem
$ ln -s test6.sh multem
$ ls -l *em
-rwxrw-r--. 1 Christine Christine 224 Jun 30 23:50 addem
lrwxrwxrwx. 1 Christine Christine   8 Jun 30 23:50 multem -> test6.sh 

$ ./addem 2 5
The calculated value is 7 

$ ./multem 2 5
The calculated value is 10 

本例从test6.sh脚本中创建了两个不同的文件名:一个通过复制文件创建(addem),另一个通过链接创建(multem)。在两种情况下都会先获得脚本的基本名称,然后根据该值执行相应的功能。

2特殊参数变量

2.1参数统计

特殊变量$#:含有脚本运行时携带的命令行参数的个数

$ cat test8.sh
#!/bin/bash
# getting the number of parameters
 echo There were $# parameters supplied.

$ ./test8.sh
There were 0 parameters supplied.

$ ./test8.sh 1 2 3 4 5
There were 5 parameters supplied.

$ ./test8.sh 1 2 3 4 5 6 7 8 9 10
There were 10 parameters supplied.

$ ./test8.sh "Rich Blum"
There were 1 parameters supplied.

如果要直接获取最后一个参数的值时,不应该用${$#},而是应该用${!#}:

$ cat test10.sh
#!/bin/bash
# Grabbing the last parameter
params=$#
echo echo The last parameter is $params
echo The last parameter is ${!#} 

$ bash test10.sh 1 2 3 4 5
The last parameter is 5
The last parameter is 5

$ bash test10.sh
The last parameter is 0
The last parameter is test10.sh

这里注意参数变量个数时不包括$0的,所以最后一个测试实例中第一行是0,而$0是程序名,所以是test10.sh

2.2抓取所有的数据

$*和[email protected]变量可以用来轻松访问所有的参数。这两个变量都能够在单个变量中存储所有的命令行参数。

$*变量会将命令行上提供的所有参数当作一个单词保存,这个单词包含了命令行中出现的每一个参数值;

[email protected]变量会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。

例子:

$ cat test10.sh
#!/bin/bash
# Grabbing the last parameter
params=$#
echo echo The last parameter is $params
echo The last parameter is ${!#} 

$ bash test10.sh 1 2 3 4 5
The last parameter is 5
The last parameter is 5

$ bash test10.sh
The last parameter is 0
The last parameter is test10.sh

3移动变量

shift命令能够用来操作命令行参数。它会根据相对位置来移动命令行参数。在使用shift命令时,默认情况下它会将每个参数变量向左移动一个位置。所以,变量$3的值会移到$2中,变量$2的值会移到$1中,而变量$1的值则会被删除(注意,变量$0的值,也就是程序名,不会改变)。

$ cat test13.sh
#!/bin/bash
count=1
while [ -n "$1" ]
do
   echo "Parameter #$count = $1"
   count=$[ $count + 1 ]
   shift
done

$ ./test13.sh rich barbara katie jessica
Parameter #1 = rich
Parameter #2 = barbara
Parameter #3 = katie
Parameter #4 = jessica

另外,你也可以一次性移动多个位置,只需要给shift命令提供一个参数,指明要移动的位置数就行了。

$ cat test14.sh
#!/bin/bash
echo "The original parameters: $*"
shift 2
echo "Here‘s the new first parameter: $1"

$ ./test14.sh 1 2 3 4 5
The original parameters: 1 2 3 4 5
Here‘s the new first parameter: 3

4处理选项

4.1查找选项

1. 处理简单选项

$ cat test15.sh
#!/bin/bash
# extracting command line options as parameters
while [ -n "$1" ]
do
  case "$1" in
-a)  echo "Found the -a option" ;;
-b)  echo "Found the -b option" ;;
-c)  echo "Found the -c option" ;;
*) echo "$1 is not an option" ;;
 esac
shift
done

  $ ./test15.sh -a -b -c -d
Found the -a option
Found the -b option
Found the -c option
-d is not an option  

2. 分离参数和选项

双破折线(--):表明选项列表结束。

$ cat test16.sh
#!/bin/bash
while [ -n "$1" ]
do
  case "$1" in
-a)  echo "Found the -a option" ;;
-b)  echo "Found the -b option";;
-c) echo "Found the -c option" ;;
 --) shift
    break ;;
*) echo "$1 is not an option";;
  esac
  shift
done
count=1
for param in [email protected]
do
  echo "Parameter #$count: $param"
  count=$[ $count + 1 ]
done

$ ./test16.sh -c -a -b test1 test2 test3
Found the -c option
Found the -a option
Found the -b option
test1 is not an option
test2 is not an option
test3 is not an option

$ ./test16.sh -c -a -b -- test1 test2 test3
Found the -c option
Found the -a option
Found the -b option
Parameter #1: test1
Parameter #2: test2
Parameter #3: test3

3. 处理带值的选项

$ cat test17.sh
#!/bin/bash
while [ -n "$1" ]
do
  case "$1" in
-a)  echo "Found the -a option";;
-b)  param="$2"
     echo "Found the -b option, with parameter value $param"
     shift ;;
-c)  echo "Found the -c option";;
--) shift
     break ;;
*) echo "$1 is not an option";;
 esac
 shift
 done
 count=1
 for param in "[email protected]"
 do
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
 done

$ ./test17.sh -a -b test1 -d
Found the -a option
Found the -b option, with parameter value test1
-d is not an option

但是这种脚本遇到$ ./test17.sh -ac的命令九九没法执行了。

4.2使用getopt命令

1. 命令的格式

getopt optstring parameters

下面是个getopt如何工作的简单例子:

$ getopt ab:cd -a -b test1 -cd test2 test3  -a -b test1 -c -d -- test2 test3

optstring定义了四个有效选项字母:a、b、c和d。冒号(:)被放在了字母b后面,因为b选项需要一个参数值。并且它会自动将-cd选项分成两个单独的选项,并插入双破折线来分隔行中的额外参数。

如果指定了一个不在optstring中的选项,默认情况下,getopt命令会产生一条错误消息。

$ getopt ab:cd -a -b test1 -cde test2 test3
getopt: invalid option -- e  -a -b test1 -c -d -- test2 test3

2. 在脚本中使用getopt

如果想忽略这条错误消息,可以在命令后加-q选项。

$ getopt -q ab:cd -a -b test1 -cde test2 test3 -a -b ‘test1‘ -c -d -- ‘test2‘ ‘test3‘

例子:

$ cat test18.sh
#!/bin/bash
set -- $(getopt -q ab:cd "[email protected]")
 while [ -n "$1" ]
 do
 case "$1" in
-a)    echo "Found the -a option" ;;
-b)    param="$2"
    echo "Found the -b option, with parameter value $param"
    shift ;;
-c) echo "Found the -c option" ;;
--) shift
     break ;;
*) echo "$1 is not an option";;
 esac
shift
done
count=1
for param in "[email protected]"
do
  echo "Parameter #$count: $param"
  count=$[ $count + 1 ]
done 

在getopt命令中仍然隐藏着一个小问题。看看这个例子:

$ ./test18.sh -a -b test1 -cd "test2 test3" test4
Found the -a option
Found the -b option, with parameter value ‘test1‘
Found the -c option
Parameter #1: ‘test2
Parameter #2: test3‘
Parameter #3: ‘test4‘

4.3使用更高级的getopts

getopts命令的格式如下:

getopts optstring variable

optstring值类似于getopt命令中的那个。有效的选项字母都会列在optstring中,如果选项字母要求有个参数值,就加一个冒号。要去掉错误消息的话,可以在optstring之前加一个冒号。getopts命令将当前参数保存在命令行中定义的variable中。

getopts命令会用到两个环境变量。如果选项需要跟一个参数值,OPTARG环境变量就会保存这个值。OPTIND环境变量保存了参数列表中getopts正在处理的参数位置。

$ cat test19.sh
#!/bin/bash
# simple demonstration of the getopts command
 while getopts :ab:c opt
 do
   case "$opt" in
a)   echo "Found the -a option" ;;
b)   echo "Found the -b option, with value $OPTARG";;
c)   echo "Found the -c option" ;;
*) echo "Unknown option: $opt";;
  esac
done

$ ./test19.sh -ab test1 -c
Found the -a option
Found the -b option, with value test1
Found the -c option

while语句定义了getopts命令,指明了要查找哪些命令行选项,以及每次迭代中存储它们的变量(opt)。getopts命令解析命令行选项时会移除开头的单破折线,所以在case定义中不用单破折线。

getopts命令有几个好用的功能。对新手来说,可以在参数值中包含空格。

$ ./test19.sh -b "test1 test2" -a Found the -b option, with value test1 test2 Found the -a option

另一个好用的功能是将选项字母和参数值放在一起使用,而不用加空格。

$ ./test19.sh -abtest1
Found the -a option
Found the -b option, with value test1

getopts命令能够从-b选项中正确解析出test1值。除此之外,getopts还能够将命令行上

找到的所有未定义的选项统一输出成问号。

$ ./test19.sh -d
Unknown option: ?

$ ./test19.sh -acde
Found the -a option
Found the -c option Unknown option: ?
Unknown option: ?

完整的例子:

$ cat test20.sh
#!/bin/bash
# Processing options & parameters with getopts
 while getopts :ab:cd opt
 do
  case "$opt" in
a)  echo "Found the -a option"  ;;
b)  echo "Found the -b option, with value $OPTARG" ;;
c)  echo "Found the -c option"  ;;
d)  echo "Found the -d option"  ;;
*) echo "Unknown option: $opt" ;;
  esac
done
shift $[ $OPTIND - 1 ]

count=1
for param in "[email protected]"
do
   echo "Parameter $count: $param"
   count=$[ $count + 1 ]
done

$ ./test20.sh -a -b test1 -d test2 test3 test4
Found the -a option
Found the -b option, with value test1
Found the -d option
Parameter 1: test2
Parameter 2: test3
Parameter 3: test4

5将选项标准化


选  项


描  述


-a


显示所有对象


-c


生成一个计数


-d


指定一个目录


-e


扩展一个对象


-f


指定读入数据的文件


-h


显示命令的帮助信息


-i


忽略文本大小写


-l


产生输出的长格式版本


-n


使用非交互模式(批处理)


-o


将所有输出重定向到的指定的输出文件


-q


以安静模式运行


-r


递归地处理目录和文件


-s


以安静模式运行


-v


生成详细输出


-x


排除某个对象


-y


对所有问题回答yes

6获得用户输入

6.1基本的读取

read命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read命令会将数据放进一个变量。下面是read命令的几种简单用法。

第一种:

$ cat test22.sh
#!/bin/bash
# testing the read -p option
read -p "Please enter your age: " age
days=$[ $age * 365 ]
echo "That makes you over $days days old! "

$ ./test22.sh
Please enter your age: 10
That makes you over 3650 days old!

第二种:

$ cat test23.sh
#!/bin/bash
# entering multiple variables
read -p "Enter your name: " first last
echo "Checking data for $last, $first…" 

$ ./test23.sh
Enter your name: Rich Blum
Checking data for Blum, Rich... 

第三种:

也可以在read命令行中不指定变量。如果是这样,read命令会将它收到的任何数据都放进特殊环境变量REPLY中。

$ cat test24.sh
#!/bin/bash
# Testing the REPLY Environment variable
read -p "Enter your name: "
echo "Hello $REPLY, welcome to my program. "

$ ./test24.sh
Enter your name: Christine
Hello Christine, welcome to my program. 

REPLY环境变量会保存输入的所有数据,可以在shell脚本中像其他变量一样使用。

6.2 超时

使用read命令时要当心。脚本很可能会一直苦等着脚本用户的输入。如果不管是否有数据输入,脚本都必须继续执行,你可以用-t选项来指定一个计时器。-t选项指定了read命令等待输入的秒数。当计时器过期后,read命令会返回一个非零退出状态码。

$ cat test25.sh
#!/bin/bash
# timing the data entry
if read -t 5 -p "Please enter your name: " name
then
    echo "Hello $name, welcome to my script"
else
    echo
    echo "Sorry, too slow! "
fi 

$ ./test25.sh
Please enter your name: Rich
Hello Rich, welcome to my script 

$ ./test25.sh
Please enter your name:
Sorry, too slow!

如果计时器过期,read命令会以非零退出状态码退出,可以使用如if-then语句或while循环这种标准的结构化语句来理清所发生的具体情况。

也可以不对输入过程计时,而是让read命令来统计输入的字符数。当输入的字符达到预设的字符数时,就自动退出,将输入的数据赋给变量。

$ cat test26.sh
#!/bin/bash
# getting just one character of input
read -n1 -p "Do you want to continue [Y/N]? " answer
case $answer in
Y | y) echo "fine, continue on…";;
N | n) echo "OK, goodbye"
       exit;;
esac
echo "This is the end of the script"

$ ./test26.sh
Do you want to continue [Y/N]? Y
fine, continue on…
This is the end of the script

$ ./test26.sh
Do you want to continue [Y/N]? n
OK, goodbye

本例中将-n选项和值1一起使用,告诉read命令在接受单个字符后退出。只要按下单个字符回答后,read命令就会接受输入并将它传给变量,无需按回车键。

6.3隐藏方式读取

有时你需要从脚本用户处得到输入,但又在屏幕上显示输入信息。其中典型的例子就是输入的密码,但除此之外还有很多其他需要隐藏的数据类型。

s选项可以避免在read命令中输入的数据出现在显示器上(实际上,数据会被显示,只是 read命令会将文本颜色设成跟背景色一样)。这里有个在脚本中使用-s选项的例子:

$ cat test27.sh
#!/bin/bash
# hiding input data from the monitor
 read -s -p "Enter your password: " pass
echo
echo "Is your password really $pass? "

$ ./test27.sh
Enter your password:
Is your password really 123456?

6.4从文件中读取

可以用read命令来读取Linux系统上文件里保存的数据。每次调用read命令,它都会从文件中读取一行文本。当文件中再没有内容时,read命令会退出并返回非零退出状态码。

$ cat test28.sh
#!/bin/bash
# reading data from a file
file="state"
count=1
cat $file | while read line
do
    echo "Line $count: $line"
    count=$[ $count + 1]
done
echo "Finished processing the file"

$ cat state
The quick brown dog jumps over the lazy fox.
This is a test, this is only a test.
O Romeo, Romeo! Wherefore art thou Romeo?

$ ./test28.sh
Line 1: The quick brown dog jumps over the lazy fox.
Line 2: This is a test, this is only a test.
Line 3: O Romeo, Romeo! Wherefore art thou Romeo?
Finished processing the file

while循环会持续通过read命令处理文件中的行,直到read命令以非零退出状态码退出。

原文地址:https://www.cnblogs.com/ericz2j/p/12045596.html

时间: 2024-08-30 04:10:35

Shell编程—处理用户输入的相关文章

【shell】Linux shell 之 判断用户输入的变量是否为数字

本文内容:判断用户输入的参数是否为数字 在shell中如何进行计算? 方式一 [[email protected] scripts]# echo $((1+2)) 3 方式二 [[email protected] scripts]# expr 2 + 3 5 [[email protected] scripts]# 注意:使用方式二的时候,要求必须要有间隔.如果使用的是乘法,号必须进行转义写为 \ [[email protected] scripts]# expr 2 * 3 expr: 语法错

Linux编程 22 shell编程(输出和输入重定向,管道,数学运算命令,退出脚本状态码)

1. 输出重定向 最基本的重定向是将命令的输出发送到一个文件中.在bash shell中用大于号(>) ,格式如下:command > inputfile.例如:将date命令的输出内容,保存到指定的输出文件中. 如果文件已存在,重定向操作符会用新的文件数据覆盖已有文件.这种情况下可以用双大于号(>>) 来追加数据.如下图所示: 2. 输入重定向 输入重定向和输出重定向正好相反.输入重定向是将文件的内容重定向到命令,而非将命令的输出重定向到文件. 输入重定向符号是小于号(<)

Linux shell脚本 判断用户输入的文件类型

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 编写一个脚本,从键盘输入一个文件,判断它是否存在,如果存在就判断它是什么类型的文件:并用对应的颜色输出 脚本如下: #!/bin/bash #function:test file type

编程:用户输入两个数,求出其加减乘除,并用消息框显示计算结果

import java.util.Scanner;import javax.swing.JOptionPane;public class FourOperationsOfTwoIntegers {public static void main(String[] args){ String firstNumber, // first string entered by usersecondNumber; // second string entered by userDouble number1,

shell脚本读取用户输入并与之交互

举个栗子: #! /bin/bash echo -e "你真要想要执行此操作吗,yes or no?" read Confirm case $Confirm in y|Y|yes|Yes) echo "做你想做的事情吧" ;; *) echo "操作终止了!" esac

shell编程:定义简单标准命令集

shell是用户操作接口的意思,操作系统运行起来后都会给用户提供一个操作界面,这个界面就叫shell,用户可以通过shell来调用操作系统内部的复杂实现,而shell编程就是在shell层次上进行编程,如Linux中的脚本编程. shenll运行原理:由消息接收.解析.执行构成的死循环. 命令行shell:该死循环包含3个模块(命令接收.命令解析.命令执行),命令行有一个标准命令集,用户输入的命令若不是标准命令,则提示用户这不是一个合法命令行,然后重新回到命令行让用户输入下一个命令. 常见的sh

linux shell编程

1.什么是shell 2. 还是hello world程序 3. shell中的变量 3.1 系统变量 3.2 用户定义变量 3.2.1 用户定义变量规则 3.2.3 shell如何使用变量 3.2.3 全局变量 vs 局部变量 4. shell编程中的控制结构 4.1 条件判定 4.1.1 简单条件判定 4.1.2 组合判定 4.2  if - else 4.3 for 4.4 while 4.5 case 5. shell中的函数 5.1 函数声明和定义 5.2 函数调用 6. shell脚

Linux学习之二十一-shell编程基础

Shell编程基础 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务.Shell 脚本(shell script),是一种为 shell 编写的脚本程序 Shell 编程跟 java.php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了 Linux中的shell种类(shell解释器的种类

Shell编程基础篇

1.变量 用户自定义变量 用户可以按照下面的语法规则定义自己的变量:变量名=变量值 .要注意的一点是,在定义变量时,变量名前不应加符号"$",在引用变量的内容时则应在变量名前加"$":在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用双引号括起来. 位置变量 通过命令行给程序传递执行参数. $0:当前执行的进程/程序名 $n:(n为1-9的数字)第几个位置参数 预定义变量 $#:命令行中位置参数的个数 $*:所有位置参数的内容 $?