linux shell 高级,Linux Shell高级技巧

本文介绍了Bash Shell编程中的几种实用技巧,包括如何在循环中正确使用管道,通过软链接名确定脚本行为,以及编写更易读的df命令输出脚本。这些技巧有助于提高脚本的灵活性和可维护性。

一、在循环中使用管道的技巧:

在Bash Shell中,管道的最后一个命令都是在子Shell中执行的。这意味着在子Shell中赋值的变量对父Shell是无效的。所以当我们将管道输出传送到一个循环结构,填入随后将要使用的变量,那么就会产生很多问题。一旦循环完成,其所依赖的变量就不存在了。

/> cat > test8_1.sh

#!/bin/sh

#1. 先将ls -l命令的结果通过管道传给grep命令作为管道输入。

#2. grep命令过滤掉包含total的行,之后再通过管道将数据传给while循环。

#3. while read line命令从grep的输出中读取数据。注意,while是管道的最后一个命令,将在子Shell中运行。

ls -l | grep -v total | while read line

do

#4. all变量是在while块内声明并赋值的。

all="$all $line"

echo $line

done

#5. 由于上面的all变量在while内声明并初始化,而while内的命令都是在子Shell中运行,包括all变量的赋值,因此该变量的值将不会传递到while块外,因为块外地命令是它的父Shell中执行。

echo "all = " $all

/> ./test8_1.sh

-rw-r--r--.  1 root root 193 Nov 24 11:25 outfile

-rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh

-rwxr-xr-x. 1 root root 108 Nov 24 12:48 test8_1.sh

all =

为了解决该问题,我们可以将while之前的命令结果先输出到一个临时文件,之后再将该临时文件作为while的重定向输入,这样while内部和外部的命令都将在同一个Shell内完成。

/> cat > test8_2.sh

#!/bin/sh

#1. 这里我们已经将命令的结果重定向到一个临时文件中。

ls -l | grep -v total > outfile

while read line

do

#2. all变量是在while块内声明并赋值的。

all="$all $line"

echo $line

#3. 通过重定向输入的方式,将临时文件中的内容传递给while循环。

done 

#4. 删除该临时文件。

rm -f outfile

#5. 在while块内声明和赋值的all变量,其值在循环外部仍然有效。

echo "all = " $all

/> ./test8_2.sh

-rw-r--r--.  1 root root   0 Nov 24 12:58 outfile

-rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh

-rwxr-xr-x. 1 root root 140 Nov 24 12:58 test8_2.sh

all =  -rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh -rwxr-xr-x. 1 root root 135 Nov 24 13:16 test8_2.sh

上面的方法只是解决了该问题,然而却带来了一些新问题,比如临时文件的产生容易导致性能问题,以及在脚本异常退出时未能及时删除当前使用的临时文件,从而导致生成过多的垃圾文件等。下面将再介绍一种方法,该方法将同时解决以上两种方法同时存在的问题。该方法是通过HERE-Document的方式来替代之前的临时文件方法。

/> cat > test8_3.sh

#!/bin/sh

#1. 将命令的结果传给一个变量

OUTFILE=`ls -l | grep -v total`

while read line

do

all="$all $line"

echo $line

done <

#2. 将该变量作为该循环的HERE文档输入。

$OUTFILE

EOF

#3. 在循环外部输出循环内声明并初始化的变量all的值。

echo "all = " $all

/> ./test8_3.sh

-rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh

-rwxr-xr-x. 1 root root 135 Nov 24 13:16 test8_3.sh

all =  -rwxr-xr-x. 1 root root 284 Nov 24 10:01 test7.sh -rwxr-xr-x. 1 root root 135 Nov 24 13:16 test8_3.sh

二、自链接脚本:

通常而言,我们是通过脚本的命令行选项来确定脚本的不同行为,告诉它该如何操作。这里我们将介绍另外一种方式来完成类似的功能,即通过脚本的软连接名来帮助脚本决定其行为。

文件名:test9.sh

#!/bin/sh

#basename命令将剥离脚本的目录信息,只保留脚本名,从而确保在相对路径的模式下执行也没有任何差异。

#通过sed命令过滤掉脚本的扩展名。

dowhat=`basename $0 | sed 's/\.sh//'`

echo $dowhat

#这里的case语句只是为了演示方便,因此模拟了应用场景,在实际应用中,可以为不同的分支执行不同的操作,或将某些变量初始化为不同的值和状态。

case $dowhat in

test9)

echo "I am test9.sh"

;;

test9_1)

echo "I am test9_1.sh."

;;

test9_2)

echo "I am test9_2.sh."

;;

*)

echo "You are illegal link file."

;;

esac

[root@wu 桌面]# ln -s test9.sh test9_2.sh

[root@wu 桌面]# ./test9_2.sh

test9_2

I am test9_2.sh.

三、编写一个更具可读性的df命令输出脚本

#!/bin/bash

#1. $$表示当前Shell进程的pid。

#2. trap信号捕捉是为了保证在Shell正常或异常退出时,仍然能够将该脚本创建的临时awk脚本文件删除。

awk_script_file="/tmp/scf_tmp.$$"

trap "rm -f $awk_script_file" EXIT

#3. 首先需要说明的是,'EOF'中的单引号非常重要,如果忽略他将无法通过编译,这是因为awk的命令动作必须要用单引号扩住。

#4. awk脚本的show函数中,int(mb * 100) / 100这个技巧是为了保证输出时保留小数点后两位。

cat < $awk_script_file

function show(size) {

mb = size / 1024;

int_mb = (int(mb * 100)) / 100;

gb = mb / 1024;

int_gb = (int(gb * 100)) / 100;

if (substr(size,1,1) !~ "[0-9]" || substr(size,2,1) !~ "[0-9]") {

return size;

} else if (mb 

return size "K";

} else if (gb 

return int_mb "M";

} else {

return int_gb "G";

}

}

#5. 在BEGIN块中打印重定义的输出头信息。

BEGIN {

printf "%-20s %7s %7s %7s %8s %s\n","FileSystem","Size","Used","Avail","Use%","Mounted"

}

#6. !/文件系统/ 表示过滤掉包含Filesystem的行,即df输出的第一行。其余行中,有个域字段可以直接使用df的输出,有的需要通过show函数的计算,以得到更为可读的显示结果。

!/文件系统/ {

size = show($2);

used = show($3);

avail = show($4);

printf "%-20s %7s %7s %7s %8s %s\n",$1,size,used,avail,$5,$6

}

EOF

df -k | awk -f $awk_script_file

[wulei@bogon 桌面]$ ./dd

FileSystem              Size    Used   Avail     Use% Mounted

/dev/sda2             17.45G   2.47G  14.09G      15% /

tmpfs                503.26M    232K 503.03M       1% /dev/shm

/dev/sda1            290.51M  31.03M 244.47M      12% /boot

Linux Shell高级技巧实战总结 一、将输入信息转换为大写字符后再进行条件判断 二、为调试信息设置输出级别 三、判断参数是否为数字 四、判断整数变量的奇偶性 五、将Shell命令赋值给指定变量,以保证脚本的移植性 六、获取当前时间距纪元时间(1970年1月1日)所经过的天数 七、非直接引用变量 八、在循环中使用管道的技巧 九、自链接脚本 十、Here文档的使用技巧 十一、获取进程的运行时长(单位: 分钟) 十二、模拟简单的top命令 十三、格式化输出指定用户的当前运行进程 十四、用脚本完成which命令的基本功能 十五、验证输入信息是否合法 十六、整数验证 十七、判断指定的年份是否为闰年 十八、将单列显示转换为多列显示 十九、将文件的输出格式化为指定的宽度 二十、监控指定目录下磁盘使用空间过大的用户 二十一、编写一个更具可读性的df命令输出脚本 二十二、编写一个用于添加新用户的脚本 二十三、kill指定用户或指定终端的用户进程 二十四、判断用户输入(是/否)的便捷方法 二十五、通过FTP下载指定的文件 二十六、文件锁定 二十七、用小文件覆盖整个磁盘 二十八、统计当前系统中不同运行状态的进程数量 二十九、浮点数验证 三十、统计英文文章中每个单词出现的频率 Linux Shell经典实例解析--Oracle启动脚本(上) Linux Shell经典实例解析--Oracle启动脚本(下)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值