收集整理的Bash技巧性学习资料

Published: Tags: SHELL LINUX

注:以下所有内容均来自网络,本人仅作收集整理用于学习 想不到我2010年发到Ubuntu论坛的帖子还在,看到就转过来了

几个 Bash 小技巧

printf '\033c' 在 Bash 中等于 clear
basename 和 dirname 是用于截路径的很好的工具

字符与ASCII码互转:
printf "%d\n" "'字母"
echo -e \\x`printf "%x" 数字`

参数的使用:
echo "-u user -p passwd -d device -v version" |sed 's/-/\n&/g'

提取指定行号的内容 :
awk 'NR==行号' 纯文本文件路径
sed -n '行号{p;q;}' 纯文本文件路径
sed -n '开始行号,结束行号p' 纯文本文件路径

为文本添加行号的几种方法
1、nl
nl 纯文本文件路径

2、awk
awk '{print NR" "$0}' 纯文本文件路径
awk '{i++;print i"\t"$0}' 纯文本文件路径

3、cat
cat -n 纯文本文件路径

4、grep
grep -n . 纯文本文件路径

5、sed
sed = 纯文本文件路径 |sed -e "N;s/\n/\t/g"

6、vim
先用 vim 打开纯文本文件,然后有两种方法:
a、:set nu
b、:%s/^/\=line('.'). ' '

删除文本行号的两种方法
行号长度固定:
cat 纯文本文件 |colrm 开始列 结束列

行号长度不固定:
sed 's/^ *[0-9]\{1,\}//' 纯文本文件

BASH 数组用法

声明一个数组:(仅支持一维数组,但参数个数没有限制)
declare -a array

也可以不声明,按数组方式直接赋值给变量即可。
数组赋值:
(1) array=(var1 var2 var3 ... varN)
(2) array=([0]=var1 [1]=var2 [2]=var3 ... [n]=varN)
(3) array[0]=var1; arrya[1]=var2; ...; array[n]=varN

计算数组元素个数:
${#array[@]} 或者 ${#array[*]}

BASH 的特殊参数 @ 和 * 都表示“从数字1开始的扩展位置参数”,但稍有差异。

引用数组:
echo ${array[n]}

遍历数组:
filename=(`ls`)
for var in ${filename[@]}; do
echo $var
done

数组实用示例:
1、从“标准输入”读入n次字符串,每次输入的字符串保存在数组array里
i=0
n=5
while [ "$i" -lt $n ]; do echo "Please input strings ... `expr $i + 1`"
read array[$i]
b=${array[$i]}
echo "$b" i=`expr $i + 1`
done

2、将字符串里的字母逐个放入数组,并输出到“标准输出”
chars='abcdefghijklmnopqrstuvwxyz'
for (( i=0; i<26; i++ )); do array[$i]=${chars:$i:1}; echo ${array[$i]}
done
这里有趣的地方是 ${chars:$i:1},表示从chars字符串的 $i 位置开始,获取 1 个字符。
如果将 1 改为 3 ,就获取 3 个字符啦~结果是:
abc
bcd
...
vxy
xyz
yz     //没有足够字符串获取了
z      //没有足够字符串获取了

3、将数组应用到shell环境变量(1)
数组赋值:
[me@jtwo ~]# SEASON=("Srping" "Summer" "Autumn" "Winter")
当你发现赋值错了,也可以立刻从新赋值纠正,如上面的 Spring 被写成 Srping。
重新赋值:(原来的值被重写)
[me@jtwo ~]# SEASON=("Spring" "Summer" "Autumn" "Winter")
查看一下环境变量:
[me@jtwo ~]# set | grep SEASON
SEASON=([0]="Spring" [1]="Summer" [2]="Autumn" [3]="Winter")
显示整个数组:
[me@jtwo ~]# echo ${SEASON[*]} 或者 echo ${SEASON[@]}
Spring Summer Autumn Winter
显示某一数组元素:
[me@jtwo ~]# echo ${SEASON[3]}
Winter
给单个数组元素赋值:
[me@jtwo ~]# SEASON[0]="New_Spring"
再查看一下看数组:
[me@jtwo ~]# echo ${SEASON[*]}
New_Spring Summer Autumn Winter
清除指定的单个数组元素:
[me@jtwo ~]# unset SEASON[2]
清除整个数组:
[me@jtwo ~]# unset SEASON

4、将数组应用到shell环境变量(2)
使用tr命令将文件中的回车转换成空格:
[me@jtwo ~]# cat /etc/shells | tr "\n" " " > /tmp/tmp.file
将文件中内容给数组赋值:(碰到第一个回车符之前的内容)
[me@jtwo ~]# read -a SHELLS < /tmp/tmp.file
查看数组赋值情况:
[me@jtwo ~]# set | grep "SHELLS"
SHELLS=([0]="/bin/sh" [1]="/bin/bash" [2]="/sbin/nologin" [3]="/bin/tcsh" [4]="/bin/csh" [5]="/bin/ksh")
这样就可以在后面将这个数组环境变量应用到其它的SHELL脚本或者应用程序里了~

Shell 字符串操作

#!/bin/bash
str="abcdefg123456789ABCDEFG"

#计算字符串的长度
echo ${#str}    #12

# 位置参数有关操作
echo ${#*}      #位置参数的个数
echo ${#@}      #(同上)
echo $*         #把所有的位置参数作为一个字符串输出
echo $@         #(同上)

#字串截取
# ${string#substring}
#      从$string的左边第一个字符截掉第一个匹配的$substring
# ${string##substring}
#      从$string的左边第一个字符截掉最后一个匹配的$substring

# 从左边开始
echo ${str#a*c}  #a到c的最短匹配
echo ${str##a*c} #a到c的最长匹配

# 从右边开始
echo ${str%a*C}     #从右边的最后一个字符开始寻找a到B的最短匹配
echo ${str%%a*B}    #从右边的最后一个字符开始寻找a到B的最长匹配

#取子串
#   ${string:position}
#   ${string:positon:length}
echo ${str:2}       #从第2个位置开始提取字符串的值
echo ${str:2:3}     #从第2个位置开始提取长度为3个字符的值

#反向提取子串
echo ${str:(-2)}        #从反向的第2个字符的位置开始提取字符串
echo ${str:(-2):6}      #从反向的第2个字符的位置开始提取长度为6个字符的串
echo ${str:(-6):3}      #从反向的第6个字符的位置开始提取长度为3个字符的串

#位置参数的提取
echo ${*:2}             #从第二个位置参数开始提取后面所有位置参数的值
echo ${*:2:3}           #从第二个位置参数开始提取后面3个位置参数的值

#子串替换
# ${string/substring/replacement}
#      使用$replacement来替换第一个匹配的$substring.
# ${string//substring/replacement}
#      使用$replacement来替换所有匹配的$substring.
#
# ${string/#substring/replacement}
#      如果$substring匹配$string的开头部分,那么就用$replacement来替换$substring.
# ${string/%substring/replacement}
#      如果$substring匹配$string的结尾部分,那么就用$replacement来替换$substring.

Shell 字符串操作

得到长度
x="abcdefg"
# 方法一
expr length $x
# 方法二
expr "$x" : ".*"
# 方法三
echo ${#x}

查找子串
expr index $x "f"

得到子串
expr substr "$x" 2 5

匹配正则表达式
# 打印匹配长度
expr match $x "."

对字符串的处理
包括:截取,连接,匹配,替换,翻转... ...
字符串的处理:
1,截取
方法一:
echo "abcdefghijklmn" |cut -b 3-9
2,翻转
echo "abcdefghijklmn" |rev

Shell 字符串操作

1、字符串剪裁
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${} 分别替换获得不同的值:
${file#*/}:拿掉第一条 / 及其左边的字串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字串:my.file.txt
${file#*.}:拿掉第一个 . 及其左边的字串:file.txt
${file##*.}:拿掉最后一个 . 及其左边的字串:txt
${file%/*}:拿掉最后条 / 及其右边的字串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字串:(显示空值)
${file%.*}:拿掉最后一个 . 及其右边的字串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 . 及其右边的字串:/dir1/dir2/dir3/my
记忆的方法为:
# 是去掉左边(在鑑盘上 # 在 $ 之左边)
% 是去掉右边(在鑑盘上 % 在 $ 之右边)
单一符号是最小匹配,两个符号是最大匹配

2、字符串的替换
x=abcdabcd
echo ${x/a/b}  # 只替换一个:bbcdabcd
echo ${x//a/b} # 替换所有:bbcdbbcd

Shell变量相关,环境变量及其文件,热键

显示环境变量
$env
$export

显示当前Shell下有效的变量
$set

输出变量
$echo $var_name

取消变量
$unset var_name

一些特殊变量
$$: 当前Shell的PID,$echo $$
$?: 上个命令的返回值,0正常,错误非0,$echo $?

关于export
如果从当前Shell中执行Bash,进入一个子Bash程序,那么当前设置的自定义变量将不存在,
子程序中只有环境变量,要让当前设置的变量在子程序中可用,可以使用:
export 变量名

关于变量有效范围
被export的变量可以称作环境变量,可以被子程序引用,其他自定义变量就不可以。
在脚本编写中,如果要在多个文件中引用一个文件中的变量,务必要用export。

变量的读取,数组,与声明

将输入内容读入变量
read -[pt] var_name
-p 加提示信息
-t 加等待秒数

declare / typeset
declare -[aixr] var
-a 定义变量为数组
-i 定义变量为整形
-x 相当于 export
-r 变量设置为只读

变量的其他设置方式

比如有两个变量:var 和 str,要根据str的值给var赋值

var=${str-expr} 如果str没设置,则var=expr,如果str设置了,则var=$str
var=${str+expr} 无论如何,var都等于expr的值
var=${str=expr} var同第一个方式,不同的是str也会改变,如果str没设置,则等于expr,否则str不变
var=${str?expr} 如果str没设置,则输出错误信息到stderr,即expr的内容,否则同第一种方式

别名 alias,unalias
就是将命令取个别名而已

用lm替代后面的长命令
$alias lm="ls -l |more"
取消lm
$unalias lm

可以将他们写到环境变量配置文件里,后面会说配置文件的内容。

历史命令 histroy
$history n  列出最近n条命令
$history -c 清除所有历史命令
-a 将新增命令写入历史文件,默认 ~/.bash_history
-r 将历史文件内容读入当前Shell历史记忆中
-w 将当前历史记忆内容写入历史文件
不加参数,则列出所有历史记录

执行命令!
!number       //执行第几个历史命令,关于编号在history命令中会显示出来
!command //执行以command开头的最近的历史命令
!!              //执行上一条命令

1. 系统设置
/etc/inputrc 所有热键在这里定义
2. 个人设置
~/.bash_profile,~/.bash_login,~/.profile 通常这三个只要一个即可,这个文件可以定义PATH等环境变量。
Bash启动时,会先读取 ~/.bash_profile,找不到时再依次寻找另外两个。

~/.bashrc,由于每次执行Shell的时候这个文件都会被执行一遍,所以再这里设置是很方便的!
至于上面提到的那几个文件,都在系统登录时只读一次。

~/.bash_history 默认的历史命令记录文件,最多存$HISTSIZE个命令
~/.bash_logout 在注销Bash的时候读取该文件,可以做一些注销之前的工作

文件读取顺序
系统先读取 /etc/profile,再根据其内容读取/etc/profile.d/中的文件等等
根据不同用户,到其个人目录中读取 ~/.bash_profile,~/.bash_login等文件
最后读取~/.bashrc文件,后面的设置会覆盖前面的。

登录Shell和非登录Shell
当登录Linux时,取得的Shell是登录Shell,后来执行的Shell是非登录Shell,X环境下启动的"终端"都是非登录Shell,
登录Shell会在登录时读取 ~/.bash_profile,~/.bash_login,~/.profile 等文件,而非登录Shell只读取 ~/.bashrc 文件。

而大部分的Linux会将~/.bashrc_profile 的内容指到~/.bashrc,这样就方便了,Ubuntu中好像没有~

列出所有的按键与按键内容
stty -a
speed 38400 baud; rows 50; columns 125; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S;
susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
比如Ctrl+D就是发送一个结束EOF信号。

要修改热键,使用“stty 热键内容 热键 格式”,比如要修改erase的热键
stty erase ^h
就可以用Ctrl+H来进行字符删除了,此时Backspace不管用了,可以用
stty erase ^?
来恢复。

一些常用热键
Ctrl+D 输入EOF
Ctrl+C 终止当前命令
Ctrl+M Enter
Ctrl+S 暂停输出
Ctrl+Q 恢复输出
Ctrl+Z 暂停当前命令

关于反引号 ` (1旁边那个)
`command` 内的命令会先执行,结果传给外部命令使用。