内部变量

• $$与$BASHPID都代表着执行程序的进程 ID,我们可以通过 echo 打印,并用 ps 指令检查得到相同的进程 ID
[root@oracle ~]# echo $BASHPID #没有结果??
[root@oracle ~]# echo $$ #显示执行进程的 id 号 [root@oracle ~]# ps ax | grep bash
? Ss : /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c
"/usr/bin/dbus-launch --exit-with-session /etc/X11/xinit/Xclients"
pts/ Ss+ : bash
? S : /bin/bash /usr/bin/eio
pts/ Ss : bash
pts/ R+ : grep bash

位置参数

我们经常向一个程序传递以空格间隔的参数,我们按先后次序分成$0(脚本本身) ,$1(参数 1),$2(参数 2).....
实例:如果没有输入参数则提示错误并显示用法,返回-1 值;输入了就说明对了,返回 0
#!/bin/bash
[ ! -n "$1" ] && echo -e "wrong\nusage : $0 canshu1 " && exit - || echo "right"
#-n 测试参数的长度是否为 ,不为 则返回 ,表示 true
测试:
[root@oracle ~]# ./f2.sh 没有接参数
wrong
usage : ./f2.sh canshu1
[root@oracle ~]# echo $? [root@oracle ~]# ./f2.sh ff 接了参数
right
[root@oracle ~]# echo $?
当这些参数在“”之间时:
• $#表示参数数量的总数,也就是总共有多少参数
• $*所有的参数以一行显示
• $@所有的参数以空格分隔
• let 可以对 C语言的表达式做计算,还有另外一种方法实现$((index+=1))
实例:区别以上符号代表的意义
、$#
#!/bin/bash
in=
for arg in "$#"
do
echo "arg $in = $arg"
let "in=in+1"
done
测试结果:$#表示参数总数
[root@oracle ~]# ./f1.sh a b c
arg =
、$*
#!/bin/bash
in=
for arg in "$*"
do
echo "arg $in = $arg"
let "in=in+1"
done
测试:$*参数以一行显示
[root@oracle ~]# ./f1.sh a b c
arg = a b c
、$@
#!/bin/bash
in=
for arg in "$@"
do
echo "arg $in = $arg"
$((in+=))
done
测试:$@参数以空格为分隔
[root@oracle ~]# ./f1.sh a b c
arg = a
arg = b
arg = c

强制退出程序本身

•$!代表进程本身
•eval可以对字符串的代码当成 bash 代码并运行,等同于` `和$( )
•(())中变量无需在变量前使用$,而且没有空格的局限性
[root@oracle ~]# vim &\
> { sleep ;
> eval 'kill -9 $!' &> /dev/null;
> }
[]
#停了 秒
[]+ Stopped vim
You have new mail in /var/spool/mail/root
[root@oracle ~]#
[]+ 已杀死 vim

字符长度

这三种方法都可以取出字符串的长度
${#string}
expr length $string
expr " $string" : ' . * '
实例:如果输入的 id 号小于 6 个字符就告诉用户是非法的 id 号,大于 6 是合法的 id 号
#!/bin/bash
echo -e "please input you id:"
read string
#ln=${#string} #这 句注释掉的和下面的那句起同样的作用
#ln=$( expr "$string" : '.*')
ln=$( expr length $string )
((ln < )) && echo "$string shi fei fa de id hao" || echo " id $string shi he fa de "

表达式方式取长度

•依据正则表达式取得相匹配部分的长度,注意表达式要用单引号
• expr match "$string"' $substring '
• expr " $string" : ' $substring'
[root@desktop Desktop]# num=1234HHHjjj123
[root@desktop Desktop]# echo $num
1234HHHjjj123
[root@desktop Desktop]# echo ${num}
1234HHHjjj123
[root@desktop Desktop]# echo ${#num}
13
[root@desktop Desktop]# echo "${num}kk"
1234HHHjjj123kk
[root@oracle ~]# stringZ=123aaa123bbb456ccc
接下来的 2 句脚本查找的是 123aaa123bbb4 的长度:13
[root@oracle ~]# echo `expr match "$stringZ" '123[a-z1-9]*.4'`
13
[root@oracle ~]# echo `expr "$stringZ" : '123[a-z1-9]*.4'`
13
123[a-z1-9]*.4:必须从字符串的开始字符匹配,[a-z1-9]表示字母 a-z和数字1-9,
*.4 表示这些字符出现任意次后以 4 结尾

符号提取

• 根据字符的位置提取字符串中一段,注意此方法索引由 0 开始
• ${string:position} 是从 0 开始的哦
• ${string:position : length} 冒号之间没有空格哦
实例:
[root@oracle ~]# stringZ=123aaa123bbb456ccc
不要前面 个字符:
[root@oracle ~]# echo ${stringZ:}
123bbb456ccc
从编号为 的字符,即第 个字符开始,提取 个字符
[root@oracle ~]# echo ${stringZ::}
aaa123

函数提取

•也可以使用 substr函数提取,注意这个函数索引从 1 开始
•expr substr $string $position $length
[root@oracle ~]# stringZ=123aaa123bbb456ccc
从第 个字符即 a 开始提取 个字符:
[root@oracle ~]# echo `expr substr $stringZ `
a123bb
实例:取一个字符串中的日期
[root@desktop Desktop]# SN=WINDD20110908DDSL
[root@desktop Desktop]# echo ${SN::}-${SN::}-${SN::}
--

前面提取字符串

• 按照正则表达式从前面开始提取字符串,注意表达式写在\ ( \ )
• expr match "$string"'\ ( $substring \ ) '
• expr " $string" : ' \($substring\ ) '
实例: stringZ=123aaa123bbb456ccc
[root@oracle ~]# echo `expr match "$stringZ" '\(123[a-z]..[1-9]*\)'`
123aaa123
[root@oracle ~]# echo `expr "$stringZ" : '\(123[a-z]..[1-9]*\)'`
123aaa123

后面提取字符串

•按照正则表达式从后面开始提取字符串,注意表达式写在\ ( \ )
•.*中“.”表示任何字符,“*”表示 0 到无穷的匹配
•expr match "$string" '.* \($substring\) '
•expr " $string" : '.*\($substring\)
实例: stringZ=123aaa123bbb456ccc
[root@oracle ~]# echo `expr "$stringZ" : '.*\([a-z]...\)'`
b456

前面字符串移除

• 按照正则表达式从前面开始移除字符串中的部分
• ${string #substring}仅移除最先匹配的部分
• ${string ##substring}只要是匹配统统移除
实例:[root@oracle ~]# stringQ=qqww20081010aabb
[root@oracle ~]# echo "${stringQ#q*w}" 最短匹配
w20081010aabb
[root@oracle ~]# echo "${stringQ##q*w}" 最长匹配
20081010aabb
实例:找出内核版本号
[root@desktop Desktop]# cat /boot/grub/grub.conf |grep kernel|grep 2.6 |cut
-d ' ' -f
/vmlinuz-2.6.-.el6.x86_64
[root@desktop Desktop]# VV=$(cat /boot/grub/grub.conf |grep kernel|grep 2.6
|cut -d ' ' -f )
[root@desktop Desktop]# echo ${VV#/[a-z]*-}
2.6.-.el6.x86_64

后面字符串移除

• 按照正则表达式从后面开始移除字符串中的部分
•${string%substring}仅移除从后面开始最先匹配的部分
•${string%%substring}只要是匹配统统移除
实例:[root@oracle ~]# stringQ=qqww20081010aabb
[root@oracle ~]# echo "${stringQ%0*b}" 从后面最短匹配
qqww2008101
[root@oracle ~]# echo "${stringQ%%0*b}" 从后面最长匹配
qqww2
练习:重命名所有在/roo/Desktop 下非 txt 后缀的文件,将其变成"txt"后缀比如"file1.TXT"将变成" file.txt" ...,这个可以很好的解决 windows 文件拷入到 Linux 中的问题
#!/bin/bash
DIR=$
fix="TXT txT tXt tXT Txt TXt TxT"
for LINE in $fix
do
old=$LINE
new=txt
for FILE in $(find $DIR -name "*.$old")
do
mv -v $FILE ${FILE%$old}$new
done
done
测试:
[root@desktop Desktop]# ./chname.sh ./
`./.TXT' -> `./2.txt'
`./.TXT' -> `./3.txt'
`./.TXT' -> `./1.txt'

表达式方式字符串替换

• 有点雷同与 sed 的表达式
• ${string / substring /replacement}首先匹配的被替换
• ${string/ /substring/replacement}匹配的全部替换
•从前面很多的例子中我们可以看到在${}中“#”代表从前面,“ %”代表从后面,因此
${string/#substring / replacement}从前面查找并替换;
${string /%substring / replacement}从后面查找并替换

参数替换

•${parameter}与直接使用$parameter 相同,但在很多的情况下使用${}可以减少歧义。
•${parameter-default} , ${parameter: -default}
•如果参数没有设置,将使用默认值
N 声明了,只是没有设置参数
[root@desktop Desktop]# N=
[root@desktop Desktop]# N1=qq
[root@desktop Desktop]# echo "${N-dd}" 没有设置参数的 N 没被替换
You have new mail in /var/spool/mail/root
[root@desktop Desktop]# echo "${N:-dd}" 没有设置参数的 N 被替换
dd
[root@desktop Desktop]# echo "${N1-dd}" 设置了参数的 N1 没被替换
qq
[root@desktop Desktop]# echo "${N1:-dd}" 设置了参数的 N1 没被替换
qq
没有声明的 N2,被默认值替换
[root@desktop Desktop]# echo "${N2-dd}"
dd
[root@desktop Desktop]# echo "${N2:-dd}"
dd
DEFAULT_FILENAME=generic.data
filename = ${1:-$DEFAULT_FILENAME}
以上两句等同于下面的一段代码
# 如果位置第一个位置参数长度为 0( 没有设置$1)
if [ ! -n $1 ]
# 那么
then
#filename 设置为缺省的值
filename=gerneric.data fi
•下面的表达式与之前的表达式雷同,细微的不同的${parameter -default}只判断参数是 否已经设置${parameter = default} ,${parameter:=default} 如果参数已经设置,但为空,将使用缺省值 echo ${username=`whoami`} 此处,之前没有定义过 username,那么变量将设置为`whoami`命令的结果
if [ -n $username ]; then
username=$username
else
username=`whoami`
fi
[root@desktop Desktop]# M=
[root@desktop Desktop]# M1=rr
[root@desktop Desktop]# echo "${M=aa}"
[root@desktop Desktop]# echo "${M:=aa}"
aa
[root@desktop Desktop]# echo "${M1=aa}"
rr
[root@desktop Desktop]# echo "${M1:=aa}"
rr
[root@desktop Desktop]# echo "${M2=aa}"
aa
[root@desktop Desktop]# echo "${M2:=aa}"
aa
•如果参数设置了,使用替换值,否则清空变量${parameter+alt} ,${parameter:+alt} 逻辑等同于:
if [ -n $parameter ]
then
parameter=$alt
else
# 清空此参数
parameter=
fi
例子:
a=${param1+xyz} # 由于 param1 没有设置所以 a 为空
echo "a = $a" # a =
param2= # param2 设置为空
a=${param2+xyz}
echo "a = $a" # 有设置将替换成缺省值 a = xyz
param3=123 # param3 设置为 123
a=${param3+xyz}
echo "a = $a" # 有设置将替换成缺省值 a = xyz
[root@desktop Desktop]# H=
[root@desktop Desktop]# H1=oo
[root@desktop Desktop]# echo "${H+yy}"
yy
[root@desktop Desktop]# echo "${H:+yy}"
[root@desktop Desktop]# echo "${H1+yy}"
yy
[root@desktop Desktop]# echo "${H1:+yy}"
yy
[root@desktop Desktop]# echo "${H2+yy}"
[root@desktop Desktop]# echo "${H2:+yy}"

错误检测

•判断参数是否设置,没有将打印后面的错误信息,${parameter ? error_msg}, $
{parameter :? error_msg}
•下面的例子可以直接对系统变量检查,如果没有设置,将直接退出程序
${HOSTNAME?} ${USER?} ${HOME?} ${MAILBOX ?}
:${ZZXy23AB ? "ZZXy23ABhasnotbeenset"}
${1 ? "Usage:$0 x.x.x.x"}# 最为简单的方式检查是否设置位置 1 参数

综合练习

实例 :
echo `basename $PWD` # 打印当前工作路径最后一段子目录名字
echo "${PWD##*/}" # 另一种方法的实现
echo `basename $` # 得到脚本的名字
echo $ # 另一种方法的实现
echo "${0##*/}" # 另一种方法的实现
filename=test.data
echo "${filename##*.}" # 移除"."之前的内容,得到 data 文件名的后缀
实例 :
下面的例子实现将特定的文件名后缀,比如 .gif 统统改为其他后缀
for filename in *.$ # 遍历当前整个目录中所有指定的文件后缀
do
mv $filename ${filename%$}$
#去除掉输入的文件名后缀再追加另外指定的一个
done
exit
实例 :
path_name=/home/bozo/ideas/thoughts.for.today
echo "path_name = $path_name"
t=${path_name##/*/} # 根据表达式最大可能的移除/部分,最后只留下文件名
echo "path_name, stripped of prefixes = $t"
t=${path_name%/} ; t=${t##*/}; # 同样的效果
实例 :下面的例子将一个用户 yangwawa 主目录的文件拷贝到另一个用户 joe(可以用$代替写在脚本中)的主目录中FILENAME=/home/yangwawa/.bash_profile
cp -v $FILENAME{,${FILENAME/yangwawa/joe}}
提取目录中的文件名:
[root@desktop Desktop]# FILENAME=/etc/sysconfig/network-scripts/ifcfg-eth0
[root@desktop Desktop]# basename $FILENAME
ifcfg-eth0
[root@desktop Desktop]# echo ${FILENAME##*/}
ifcfg-eth0
[root@desktop Desktop]# echo ${FILENAME%/*}
/etc/sysconfig/network-scripts
拼接目录:
[root@desktop Desktop]# BACK_DIR=/usr/local/share
[root@desktop Desktop]# echo $BACK_DIR/${FILENAME##*/}
/usr/local/share/ifcfg-eth0
替换文件路径中目录的名字:
[root@desktop Desktop]# FILENAME=/home/student/.mozilla/firefox/profiles.ini
[root@desktop Desktop]# echo ${FILENAME/student/visitor}
/home/visitor/.mozilla/firefox/profiles.ini

定义一个变量

declare -r 定义一个只读变量
declare -i 定义的变量是一个数字,对于数字变量可以不用在变量名前使用"$"符号
declare -a 定义的是数组
declare -f 定义的是函数
declare -x 定义的变量在 bash 中等同于 export 可以为其他程序所用

declare 显示变量

• declare 命令对于标识变量也非常有用
bash$ declare | grep HOME
/home/bozo
bash$ zzy=68
bash$ declare | grep zzy
zzy=68
bash$ Colors=([0]="purple" [1]="reddish-orange" [2]="light green")
bash$ echo ${Colors[@]}
purple reddish-orange light green
bash$ declare | grep Colors
Colors=([0]="purple" [1]="reddish-orange"[2]="light green")

数组概述

• 申明 数组
declare - aarray
array[xx]
• 调用 时
${array[ xx] }

数组使用

打印书名:
#!/bin/bash
declare -a BOOKS
BOOKS[]="Windows 2007"
BOOKS[]="Windows xp"
BOOKS[]="Oracle"
BOOKS[]="IBM ATX 5"
BOOKS[]="RedHat"
echo "${BOOKS[@]}" #将数组作为一串字符打印出来
echo ++++++++++++++++++++++
TOTAL=${#BOOKS[@]} #以空格为依据取字符串的长度
for ((X_B=;X_B<TOTAL;X_B++))
do
echo "$X_B --> ${BOOKS[$X_B]}"
done
测试:
[root@desktop Desktop]# chmod u+x showbooks.sh
[root@desktop Desktop]# ./showbooks.sh
Windows Windows xp Oracle IBM ATX RedHat
++++++++++++++++++++++
--> Windows
--> Windows xp
--> Oracle
--> IBM ATX
--> RedHat

BASH 编程之变量高级篇的更多相关文章

  1. bash编程-Shell变量

    bash中,所有变量的值默认均为字符串. 1. 变量操作 调用变量 $变量 查看变量(所有类型) set 删除变量 unset 变量 2. 变量分类 2.1 自定义变量 自定义变量仅对当前Shell有 ...

  2. 怎样用 Bash 编程:逻辑操作符和 shell 扩展

    学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇. Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本.本系列(三篇文章,基于我的 三集 Linux 自学课程 ...

  3. Bash 脚本编程的一些高级用法

    概述 偶然间发现 man bash 上其实详细讲解了 shell 编程的语法,包括一些很少用却很实用的高级语法.就像发现了宝藏的孩子,兴奋莫名.于是参考man bash,结合自己的理解,整理出了这篇文 ...

  4. 脚本编程中的test、bash调试、变量计算、参数

    脚本编程中的test.bash调试.变量计算.参数 1.文件测试 -e FILE:测试文件是否存在 -f FILE:测试文件是否为普通文件 -d FILE:测试路径是否为目录 -r FILE:测试当前 ...

  5. (十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. Kotlin——从无到有系列之高级篇(一):Lambda表达式

    如果您对Kotlin很有兴趣,或者很想学好这门语言,可以关注我的掘金,或者进入我的QQ群大家一起学习.进步. 欢迎各位大佬进群共同研究.探索 QQ群号:497071402 进入正题 经过前面一系列对K ...

  7. 常见 Bash 内置变量介绍

    目录 $0$1, $2 等等$#$* 与 "$*"$@ 与 "$@"$!$_$$$PPID$?$BASH$BASH_VERSION$EUID 与 $UID$GR ...

  8. 大数据系列博客之 --- 深入简出 Shell 脚本语言(高级篇)

    首先声明,此系列shell系列博客分为四篇发布,分别是: 基础篇:https://www.cnblogs.com/lsy131479/p/9914747.html 提升篇:https://www.cn ...

  9. Bash拾遗:变量

    使用引号包裹变量 在<高级Bash脚本编程指南>中的4.1节中有这么个例子: hello="A B C D" echo $hello # A B C D echo &q ...

随机推荐

  1. Windows系统调用中API的3环部分(依据分析重写ReadProcessMemory函数)

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中API的3环部分 一.R3环API分析的重 ...

  2. CEILING保留n位小数向上取整

    number=3.1415926 CEILING(number*POWER(10,n))/POWER(10,n) 思路为:乘以10的n次方得到要保留的小数部分并转换为整数,再用CEILING向上取整, ...

  3. windows离线安装sublime插件:ctags

    网络上一堆安装ctags教程,可都是在线安装. 花了点时间摸索出了离线安装教程. 1. 准备好sublime 和 package control sublime我用的版本是text 2. text 3 ...

  4. 基于powershell的socks代理

    0x01 前言 在实战中,内网的代理尤其重要,而常见的端口转发被反病毒软件已经盯死,那么学习使用基于powershell的渗透脚本进行代理.端口转发的非常有必要的. 0x02 使用 介绍ithub: ...

  5. Cocos2d-x 学习笔记(9) Action 运行原理

    1. 从一个Action开始 1.1 创建 在Scene里写一个Sprite,并添加Action: Sprite *sp = Sprite::create("m1.png"); M ...

  6. 真——Springcloud支持Https

    很久不写了,因为一直没有一个项目的需求推动,担心写的东西可能不是太实际.其间学习的事倒是做了不少,设计模式.领域开发.Antlr.kubernetes等等,其实大部分都记在纸质笔记上了.. 基于对新技 ...

  7. c使用二叉链表创建二叉树遇到的一些疑问和思考

    二叉链表存储二叉树 学习的时候参考的是<大话数据结构>,书中是这样定义的 typedef char TElemType; typedef struct BiTNode { TElemTyp ...

  8. Spring Boot入门(二):获取配置文件值

    本篇博客主要讲解下在Spring Boot中如何获取配置文件的值. 1. 使用yaml配置文件 Spring Boot默认生成的配置文件为application.properties,不过它也支持ya ...

  9. ESP8266开发之旅 网络篇③ Soft-AP——ESP8266WiFiAP库的使用

    1. 前言     在前面的篇章中,博主给大家讲解了ESP8266的软硬件配置以及基本功能使用,目的就是想让大家有个初步认识.并且,博主一直重点强调 ESP8266 WiFi模块有三种工作模式: St ...

  10. 学习python3高阶函数笔记和demo

    python的高阶函数的定义是:一个函数接收另一个函数作为参数,这种函数就称之为高阶函数 举一个最简单的例子: def text(a,b,c): return c(a)+c(b) print( tex ...