第1节:Shell入门基础知识

本文主要介绍了Bash脚本的相关知识。包括开头和结尾的格式,脚本参数如$#、$0等的含义,特殊环境变量IFS作为分隔符的作用,echo命令不同用法及对应字符解释,最后还提及了实例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,格式

  • 开头格式:#!/bin/bash
  • 结尾格式:#$?

2,参数

  • $# 是传给脚本的参数个数
  • $0 是脚本本身的名字
  • $1 是传递给该shell脚本的第一个参数
  • $2 是传递给该shell脚本的第二个参数
  • $@ 是传给脚本的所有参数的列表
  • $* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
  • $$ 是脚本运行的当前进程ID号
  • $? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

3,IFS

  • IFS:为shell的特殊环境变量作为分隔符来用
    #!/bin/bash
    IP=192.168.2.1
    echo $IP
    IFS="."
    echo $IP
    输出结果为: 
    192.168.2.1
    192 168 2 1
    

4,echo命令

  • echo:输出字符串结尾有换行符;
  • echo -n “”:输出字符串去掉结尾的换行符
  • echo -e “”:出现以下字符进行解释
    • “\a”:警示字符;
    • “\b”:退格;
    • “\c”:忽略最后的换行符;
    • “\f”:清屏;
    • “\n”:换行;
    • “\r”:回车;
    • “\0ddd”: 将字符表示成1到3位的八进制数值

5,实例代码

#!/bin/bash

# 1
#单引号标记字符串
echo 'The time and date are :'
#使用命令
date
#双引号标记字符串
echo "Let's see who's logged into the system:"
#使用命令
who
#去掉末尾换行符 -n
echo -n "Time are:"
date


#2
#使用环境变量
echo "User info for userid: $USER"
echo "UID: $UID"
echo "HOME: $HOME"
#使用转义字符
echo "The cost of the item is \$15"
#用户自定义变量
days=10
guest="Katie"
echo "$guest checked in $days days ago"


#3
#反引号允许把命令输出给变量
testing='date'
echo "The date and time are:"$testing
#用反引号捕获当前日期,并用它在脚本中创建唯一的文件名,这是一种为日志文件名提取日
#期信息的常用技术;+%y%m%d格式指示date命令使用两位数来显示年,月,日
today='date +%y%m%d'
ls /usr/bin -al > log.$today


#4
#输出重定向 command > outputfile
#创建文件,重写文件内容
data >  log.txt
#附加数据到现有文件
data >> log.txt
#输入重定向 command < inputfile
#wc命令计数内置输入重定向提供的数据的行,单词,字节的数目
wc   <  log.txt



#5
#当为一个变量指定数字时,使用美元符号和方括号($[operation])
var1 = $[1+5]
echo $var1
var2 = $[$var1 * 2]
echo $var2


#6
#浮点数解决方案,使用内置的bash计算器(成为bc)
#bash计算器实际上是一种编程语言,该语言允许在命令行中输入浮点数表达式,然后计算它们
#在脚本中使用bc:variable='echo "options; expression" | bc'
#scale:浮点数输出位数
var3 = 'echo "scale=4; 3.44/5" | bc'
echo The answer is $var3

#7
#使用内置输入重定向方法,而不使用文件重定向;内置输入重定向允许从命令行直接定向数据
#EOF文本字符串表明内置重定向数据的开始和末尾
#variable='bc << EOF
#options
#statements
#expressions
#EOF
#'
var4=10.46
var5=43.67
var6=33.2
var7=71
var8='bc << EOF
a1 = ($var4 * $var5)
b1 = ($var6 * $var7)
a1+b1
EOF
'



#8
#脚本使用if行的date命令,如果命令执行成功,echo语句将显示文本字符串
if date
then
  echo "it worked"
fi

if hello
then 
  echo "it worked"
else
  echo "it not worked"
fi



#9
#数字比较 
#-eq:是否相等;-ge:大于或等于;-gt:大于;-le:小于或等于;-lt:小于;-ne:不相等
data1 = 10
data2 = 11
if [$data1 -eq $data2]
then 
  echo "The value are equal"
else
  echo "The value are different"
fi
#字符串比较
#=:是否相同;!=:是否不同;<:是否小于;>:是否大于;
#-n str:是否大于;-z str:是否为0
testuser=rich
if [@USER != $testuser]
then
  echo "This isn't $testuser"
else
  echo "Welcome $testuser"
fi
#字符串大小比较需要用转义字符或者会被认为:重定向字符
str1=baseball
str2=hockey
if [$str1 \> $str2]
then 
  echo "$str1 is greater than $str2"
else
  echo "$str1 is less than $str2"
fi
#文件比较
#-d file:是否存在并且是一个目录;-e file:是否存在;-f file:是否存在并且是一个文件
#-r :是否存在并可读;-s:是否存在并不为空;-w:是否存在并可写;-x:是否存在并可执行
#file1 -nt file2:file1是否比file2新;file1 -ot file2:file1是否比file2旧;
if [-d $HOME]
then
  echo "Your HOME directory exists"
  cd $HOME
  ls -a
else
  echo "There's a problem with your HOME directory"
fi


#10
#复合条件检查
if [-d $HOME] && [-w $/HOME/testing]
then
  echo "The file exists and you can write to it"
else
  echo "I can't write to the file"
fi


#11
#双圆括号:允许在比较中包含高级数学公式 ((expression))
#val++:后增量;val--:后减量;++val:前增量;--val:前减量;!:逻辑否定
#~:取反;**:取幂;<<:左移;>>:右移;&:布尔逻辑与;|:布尔逻辑或;
#&&:逻辑与;||:逻辑或
data3=10
if (($data3**2 > 90))
then
  ((data4=$data3**2))
   echo "The square of $data3 is $data4"
fi

#12
#双方括号:[[expression]]模式匹配,可以定义与字符串值相匹配的正则表达式
if [[$USER == r*]]
then
  echo "Hello $USER"
else
  echo "Sorry, I don't know you"
fi

#13
#case语句
case $USER in
rich | barbara)
  echo "welcom, $USER";;
testing)
  echo "please enjoy your visit";;
jessica)
  echo "Don't forget to log off";;
*)
  echo "Sorry";;
esac

#$?
#循环的相关使用
#!/bin/bash
echo "*****************1************************"
for num in 1 2 3 4 5 6 7 8 9 10			    #for循环格式
do
	echo -n "num=$num; "			        #-n:去掉最后换行符			
done
echo	-e "\nnum=$num"				        #-e:进行转义


echo "*****************2************************"
for test in I do\`t know if this\`ll work	#特别字符处理
do 
	echo "word:$test"
done


echo "*****************3************************"
for num in "num 1" "num 2" "num 3" "num 4" "num 5" "num 6" "num 7" "num 8" "num 9"
do 						                    #带空格字符处理
	echo -n "$num; "
done
echo -e "\n$num"


echo "*****************4************************"
list="1 2 3 4 5 6 7 8 9 10"			        #使用变量,赋值时 “=”左右不能有空格
for num in $list		
do
	echo -n "num=$num; "						
done
echo	-e "\nnum=$num"				

echo $?


echo "*****************5************************"
for num in `cat hello`				       #使用命令
do
	echo -n "num=$num; "
done
echo	-e "\nnum=$num"


echo "*****************6************************"
for file in /home/zzy/*				      #使用通配符读取目录
do 
	if [ -d "$file" ]
	then
		echo "Dir=$file"
	elif [ -f "$file" ]
	then
		echo "File=$file"
	fi
done


echo "*****************7************************"
for ((i=0; i<10; i++))				      #C模式循环
do
	echo -n "num=$i; "
done
echo	-e "\nnum=$i"


echo "*****************8************************"
var1=10
while [ $var1 -gt 0 ]				      #while循环
do
	echo -n "var=$var1; "
	var1=$[$var1-1]
done
echo	-e "\nvar=$var1"

echo "*****************9************************"
var1=100					              #until循环
until [ $var1 -eq 0 ]
do 
	echo -n "var1=$var1; "
	var1=$[$var1-25]
done
echo	-e "\nvar1=$var1"

echo "****************10************************"
IFS_OLD=$IFS					         #文件数据循环
IFS=$'\n'
for entry in `cat hello`
do
	echo "$entry"
done
IFS=$IFS_OLD

echo "****************11************************"
for var in 1 2 3 4 5 				     #退出循环
do
	echo "var=$var"
	if [ $var -eq 2 ]
	then
		break;				             #break n:n=1退出当前循环;n=2退出外部循环
	fi
done

echo "****************12************************"
for var in 1 2 3 4 5				    #结束本次循环
do
	if [ $var -eq 2 ];then
		continue;
	fi

	echo "var=$var"
done > output.txt				        #输出到文件

#$?


输出结果:
*****************1************************
num=1; num=2; num=3; num=4; num=5; num=6; num=7; num=8; num=9; num=10; 
num=10
*****************2************************
word:I
word:do`t
word:know
word:if
word:this`ll
word:work
*****************3************************
num 1; num 2; num 3; num 4; num 5; num 6; num 7; num 8; num 9; 
num 9
*****************4************************
num=1; num=2; num=3; num=4; num=5; num=6; num=7; num=8; num=9; num=10; 
num=10
0
*****************5************************
cat: hello: No such file or directory

num=10
*****************6************************
*****************7************************
num=0; num=1; num=2; num=3; num=4; num=5; num=6; num=7; num=8; num=9; 
num=10
*****************8************************
var=10; var=9; var=8; var=7; var=6; var=5; var=4; var=3; var=2; var=1; 
var=0
*****************9************************
var1=100; var1=75; var1=50; var1=25; 
var1=0
****************10************************
cat: hello: No such file or directory
****************11************************
var=1
var=2
****************12************************
#脚本参数和用户输入处理
#!/bin/bash
echo "The code name is $0"		    #$0 程序名称
if [ -n "$1" ];then
echo "The first para is $1"		    #$1 第一个参数
fi
if [ -n "$2" ];then
echo "The second para is $2"		#$2 第二个参数
fi
if [ -n "$1" ] && [ -n "$2" ];then
var1=$[ $1+$2 ]
echo "The total value is $var1"
fi


if [ -n "$1" ]				        #判断长度是否大于0
then
	echo "hello  $1"
else
	echo "sorry no para"
fi

echo "all para num = $#"		     #$#  总参数个数

echo "the last para is ${!#}"		 #${!#} 最后一个参数

echo "\$* all pare = $*"		#$* 输出所有参数,把参数作为一个单词
echo "\$@ all_pare = $@"		#$@ 输出所有参数,把参数作为一个字符串

#$*与$@的不同
coutn=1
for param in "$*"
do
	echo "\$* Parameter #$count=$param"
	count=$[$count+1]
done

count=1
for param  in "$@"
do 
	echo "\$@ Parameter #$count=$param"
	count=$[$count+1]
done
#运行脚本:
# ./test12 rich barbara
#输出结果:
# $*   Parameter #1=rich barbara
# $@ Parameter #1=rich
# $@ Parameter #2=barbara



#使用shift命令时,默认将每一个参数变量左移一个位置,$3值移给$2,$2值移给$1,$1值被丢弃
count=1
while [ -n "$1" ]
do 
	echo "pare #$count = $1"
	count=$[ $count + 1 ]
	shift				                  #参数左移 $1丢弃
done
#运行脚本:
# ./test12 rich barbara katie
#输出结果:
# $@ Parameter #1=rich
# $@ Parameter #2=barbara
# $@ Parameter #3=katie


#处理带参数的选项
while[-n "$1"]
do
	case "$1" in
	-a)  echo "Found the -a option";;
	-b)  param = "$2"
		  echo "Fount the -b option, with parameter value $param"
		  shift 2;;
	-c) echo "Found the -c option";;
	--) shift 
		 break;;
	*)  echo "$1 is not an option";;
	esac
	shift
done
#运行脚本:
# ./testing -a  -b test1 -c -d 
#输出结果:
# Found the -a option
# Found the -b option, with parameter value test1
#-d is not an option


#getopt命令可以接受任意形式的命令行选项和参数列表,并自动将这些选项和参数转换为
#合适的格式,命令格式:getopt options optstring parameters(optstring:选项
#字符串,定义命令行中的有效选项字母,它还定义哪些选项字母需要参数值),在选项字符
#串中列出将在脚本中用到的每个命令行选项字母,然后在每个需要参数值的选项字母后面放
#置一个冒号
getopt ab:cd -a -b test1 -cde      # "ab:cd":选项字符串 b:表示b需带参数	
					               # "-a -b test1 -cde":输入参数 
                                   # 其中-cde被分解成'-c' '-d' '-e' e:因为选项字符串中没有报错
getopt -q ab:cd -a -b test1 -cde	  # -q:忽略 -e 报错

getopt -q ab:cd -a -b -c meng xiang   #输出结果:-a -b '-c' -- 'meng 'xinag' 
					                  #默认把'-c'作为-b的参数 用'--' 来分割额外的参数

#set命令的一个选项是双破折号,表示将命令行参数变量替换为set命令的命令行中的值
#这个技巧是:将原始脚本命令行参数送给getopt命令,然后将getopt命令的输出送给
#set命令,以便将原始命令行参数替换为通过getopt格式化过的更精细的形式
set -- `getopt -q ab:cd "$@"`	#将命令行参数变量替换为set命令行命令中的值
while [ -n "$1" ]			    #操作参数和选项参数分离 		
#do					            #getopt:为所处理的选项和参数生成一个输出
	case "$1" in
	-a)
	   echo "Found the -a option";;
	-b)
	   echo "Found the -b option";;
	-c)
	   echo "Found the -c option";;
	--)
	   shift
	   break;;
	*)
	   break;;
	esac
	shift
done
#运行脚本:
# ./testing -a  -b test1 -c -d 
#输出结果:
# Found the -a option
# Found the -b option, with parameter value test1
#-d is not an option
 
#每调用一次getopts,它只处理在命令中监测到的参数中的一个,处理完所有参数后,以大于零的状态退出
#getopts命令的格式为:getopts optstring variable
while getopts :ab:c opt	  #getopts:对shell参数变量进行处理
do 					      #在选项字符串前面加‘:’表示忽略错误
	case "$opt" in		  #每调用一次getopts,它只处理命令中检测到灯参数中的一个,处理完所有参数后
	a) echo "Found the -a option";;      #以大于零的退出状态退出
	b) echo "Found the -b option, with value $OPTARG";; 
	c) echo "Found the -c option";;      #OPTIND:getopts停止处理时在shell参数列表中的位置
	*) echo "Unkonwn option: $opt";;     #OPTARG:包含需要参数值的选项要使用的值 此处为-b的参数
	esac
done
shift $[ $OPTIND-1 ]					 #移除命令选项,使参数从$1开始
count=1
for para in $@
do
	echo "Para #$count $para"
	count=$[ $count+1 ]
done
#运行脚本:
# ./testing -ab test1 -c 
#输出结果:
# Found the -a option
# Found the -b option, with parameter value test1
#Found the -c option


#read命令接受标准输入(键盘)的输入,或其他文件描述符的输入,得到输入后,read命令将数据放入
#一个标准变量中
echo -n "Enter your name:"
read name						    # 读取键盘命令
echo "hello $name"

read -p "Enter your age:" age	    # "-p"选项,允许在read命令中直接进行一行提示
echo "you live $age year"


read -p "Enter your name and age:" name age	 # 多个参数
echo "hello $age $name"                      # 如果不指定变量,变量默认存储在REPLY中

 # "-t"计时选项:当计时器计时满时,返回一个非零状态
if read -t 5 -p "Please enter your name:" name
then
	echo "hello $name, welcome"
else
	echo "sorry too slow"
fi


read -n1 -p "Enter your choice:[Y?N]?" answer	 # "-n1":表示允许读取一个字符
case $answer in
Y | y) echo ""
       echo "fine, OK come on";;
N | n) echo ""
       echo "OK, goodbye";;
esac


read -s -p "Enter your password" pass			 # "-s":表示输入不进行回显
echo ""
echo "right pass"

count=1
cat hello | while read line	     # "读取文件":每次读取一行,当没有文件可读时,返回非零状态
do 
	echo "Line $count1: $line"
	count=$[ $count+1]
done
#数据显示
#linux使用文件描述符:标识每个文件对象,文件描述符是一个非负整数,可以唯一地标识会话中打开的文件
#linux标准文件描述符: 0:STDDIN:标准输入;1:STDOUT:标准输出;2:STDERR:标准错误
#!/bin/bash
echo "This is error out"  >&test6			#临时重定向 >&file
echo "This is normal"

#exec 1>test7						        #永久重定向,下面输出到test7文件中
#echo "hello long world"
#echo "hello samll world"

#exec 0<hello						        #重新定向输入
#count=1
#while read line
#do
#	echo "Line #$count:$line"
#	count=$[ $count + 1 ]
#done


exec 3>&1						           #重新定向文件描述符
exec 1>test6
echo "This should store in the output file"
exec 1>&3
echo "Now come back"

exec 6<&0						           #创建输入文件描述符
exec 0<hello
count=1
while read line
do
	echo "Line #$count:$line"
	count=$[ $count + 1 ]
done
exec 0<&6

read -n1 -p "Are you done now:" answer
case $answer in
Y | y) echo -e "\nGood come on";;
N | n) echo -e "\nSorry GoodBye";;
 *)    echo -e "\nError GoodBye" ;;
esac


exec 3>test6
echo "This is a test" >&3
exec 3>&-					        #关闭文件描述符
#echo "This won\`t work" >&3

ls -al > /dev/null			        #禁止命令输出

mktemp test9.XXXXXX				    #创建临时文件 用此格式确保文件在目录中的唯一性
mktemp test9.XXXXXX
ls -al test9.*
rm -rf test9.*

mktemp -t test9.XXXXXX				#强制在/tmp中创建文件
ls -al /tmp/test9.*
rm -rf /tmp/test9.*

mktemp -d dir.XXXXXX				#创建临时目录
ls -al dir.*
rm -rf dir.*

echo "hello world 1" >&test6
echo "hello world 2" >&test6

echo "hello world 1" | tee test7		#相当于重定向,但是支持标准输出和消息同时记录
echo "hello world 2" | tee -a test7
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值