您的位置:首页 > 运维架构 > Shell

《linux Shell 脚本攻略》进阶学习(第二部分)

2013-07-17 13:51 513 查看
第三章 以文件之名
生成任意大小的文件
$ dd if=/dev/zero of=junk.data bs=1M count=1
记录了1+0 的读入
记录了1+0 的写出
1048576字节(1.0 MB)已复制,0.735955 秒,1.4 MB/秒

查找并删除重复文件
条件:删除那些虽然名字不同但内容一模一样的文件
通过文件内容来识别他们,校验和是依据文件内容来计算的,内容相同的文件自然就生成想通的校验和
通过比较校验和来删除重复文件
书本代码有误,补充如下

#!/bin/bash
ls -lS | awk 'BEGIN{
getline;getline;
name1=$9;
size=$5
}
{
name2=$9;
if (size==$5)
{
"md5sum $name1"  | getline;csum1=$1;
"md5sum $name2"  | getline;csum2=$1;
if (csum1==csum2)
{
print name1;
print name2;
}
};
size=$5;
name1=name2;
}' | sort -u > duplicate_files
cat duplicate_files | xargs -I {} md5sum {} | sort | uniq -w 32 | awk '{ print $2 }' | sort -u > duplicate_sample
echo Removing..
comm duplicate_files duplicate_sample -2 -3 | tee /dev/stderr | xargs rm -f
echo Removed duplicates files successfully.
rm duplicate_sample duplicate_files


以不同的用户运行可执行文件
原理:有一个叫做setuid的特殊文件权限,它允许其他用户以文件所有者的身份来执行文件
chown root.root execu_file
chown +s execu_file
./execu_file
这个文件事实上每次以超级用户来运行
setuid的使用不是无限制的,它只能应用在linux ELFG格式二进制文件上,二不能用于脚本

创建文件不可修改
限制:一旦文件呗设置为不可修改,任意用户包括超级用户都不能删除文件,除非其不可修改的属性被移除

通过查看/etc/mtab文件,很容易找出所有挂载分区的文件系统类型
cat /etc/mtab
/dev/sda1 / ext4 rw,errors=remount-ro 0 0
proc /proc proc rw,noexec,nosuid,nodev 0 0
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
none /sys/fs/cgroup tmpfs rw 0 0
none /sys/fs/fuse/connections fusectl rw 0 0
none /sys/kernel/debug debugfs rw 0 0
none /sys/kernel/security securityfs rw 0 0
udev /dev devtmpfs rw,mode=0755 0 0
devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=0620 0 0
tmpfs /run tmpfs rw,noexec,nosuid,size=10%,mode=0755 0 0
none /run/lock tmpfs rw,noexec,nosuid,nodev,size=5242880 0 0
none /run/shm tmpfs rw,nosuid,nodev 0 0
none /run/user tmpfs rw,noexec,nosuid,nodev,size=104857600,mode=0755 0 0
binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,noexec,nosuid,nodev 0 0
gvfsd-fuse /run/user/zhangjianlin/gvfs fuse.gvfsd-fuse rw,nosuid,nodev,user=zhangjianlin 0 0

可以用chattr将文件设置为不可修改
实战演练
将一个文件设置为不可修改
chattr +i file
或者sudo chattr +i file
rm file出错
移除不可修改的属性
chattr -i file

修改文件三个时间
touch -a 更文件访问时间
touch -m 更改文件内容修改时间
touch -d 时间戳

列举文件夹下的类型统计信息
file -b filename
ASXII text

脚本如下

#!/bin/bash
if [ $# -ne 1 ];
then
echo $0 basepath;
echo
fi
path=$1
declare -A statarray
while read line;
do
ftype=`file -b "$line"`
let statarray["$ftype"]++;
done< <(find $path -type f -print)

echo ========file types and counts==========
for ftype in "${!statarray[@]}";
do
echo $ftype : ${statarray["$ftype"]}
done
结果
$ bash filestat.sh .
========file types and counts==========
Bourne-Again shell script, ASCII text executable : 2
empty : 2

原理

while read line
do
echo $line
done<A
<A写在最后相当于给整个while do 语句加了一个约束条件,读取文件A里每行至文件尾结束


while read line<A
do
echo $line
done
<A写在前面,整个while do语句就没有约束条件, 因为 read line<A这个始终为真
表示 不停地 读取A中的第一行,赋值给参数line,然后打印参数line的值.

done< <(find $path -type f -print)
<(find $path -type f -print) 等同与文件名。只不过他用子进程输出代替文件名

${!statarray[@]} 用于返回一个数组索引列表

第四章。让文本飞

正则表达式入门
更多内容百度

匹配一个ip地址
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

grep搜索文本

扩展内容
递归搜索包含词的文件
grep "text" . -R -n #开发人员常用的命令

$ grep "bin" . -R -n
./第三章:42:binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,noexec,nosuid,nodev 0 0
./第三章:66:#!/bin/bash
./second/mvsuffix.sh:1:#!/bin/bash
./second/mvfilename.sh:1:#a!/bin/bash
./touchlearnfiles.sh:1:#!/bin/bash
./第一章.txt:25:#!/bin/bash
./第一章.txt:36:#!/bin/bash
./第一章.txt:45:#!/bin/bash
./第一章.txt:71:#!/bin/bash
./第一章.txt:74:(cd /bin; ls);
./第一章.txt:97:#!/bin/bash
./第一章.txt:117:#!/bash/bin
./第一章.txt:133:line="root:x:0:0:root:root:/bin/bash"
./第一章.txt:178:#!/bin/bash
./first/password.sh:1:#!/bin/bash
./first/dealpasswd.sh:1:#!/bash/bin
./first/dealpasswd.sh:17:line="root:x:0:0:root:root:/bin/bash"
./first/IFSofdiv.sh:1:#!/bin/bash
./first/array_var.sh:1:#!/bin/bash
./first/cilldshell.sh:1:#!/bin/bash
./first/cilldshell.sh:4:(cd /bin; ls);
./first/delaysleep.sh:1:#!/bin/bash
./first/filetest.sh:1:#!/bin/bash
./第二章.txt:160:#a!/bin/bash
./第二章.txt:196:#!/bin/bash
./third/filestat.sh:1:#!/bin/bash
./third/remove_duplicates.sh:1:#!/bin/bash

在grep 搜索中包括或排除文件
只在目录中递归搜索所有的.c .cpp文件:
$ grep "main()" . -r --include *.{c,cpp}
搜索中排除所有的README文件
$ grep "main()" . -r --exclude "README"

对文件中的行、单词和字符进行迭代
实战
迭代文件中的每一行
while read line;
echo $line;
done < file.txt

每一行的单词
for word in $line
do
echo $word ;
done

迭代一个单词中方的每一个字符
for ((i=0;i<${#word};i++))
do
echo
${word:i:1};
done

${word:start_position:no_of_characters} 返回变量word所包含的字符串中的一个字窜 :重要

cat touchlearnfiles.sh | (while read line; do echo $line; done)

结果:

#!/bin/bash

arrays=("一" "二" "三" "四" "五" "六" "七" "八" "九" "十")
arraynums=(first second third fourth fifth sixth seventh eighth ninth tenth)
read -p "please input the number of caption:" num;

touch "第${arrays[$num-1]}章.txt"
mkdir ${arraynums[$num-1]}

awk打印多列数据,并在列间插入指定的字符
$ ls -l | awk '{ print $1" : " $8 }'


实战演练:打印不同行或样式之间的文本

打印从第M行到N行这个范围内的所有文本,使用下面语法:
$ awk 'NR==M, NR==N' filename

把M跟N换成数字
$ seq 100 | awk 'NR==4, NR==6'

要打印处于'/start_pattern/,/end_pattern/' filename


$ cat section.txt
line with pattern1
line with pattern2
line with pattern3
line end with pattern4
line with pattern5

$awk '/pa.*3/, /end/' section
line with pattern3
line end with pattern4

回文判断 最简单的使用命令rev命令
rev 接受一个文件或stdin作为输入,并逆序打印每一行内容
试试下面的代码

#/bin/bah
string="malayalam"
if [[ "$string" == "$(echo $string | rev )" ]]; #重点
then
echo "Palindrome"
else
echo "not palindrome"
fi
解析文本中的点子邮件地址和url
解析email
egrep -o '[A-Za-z0-9.]+@[A-Za-z0-9.]+\.[a-zA-Z]{2,4}'
匹配HTTP URL的正则表达式
egrep -o "http://[a-zA-Z0-9.]+\.[a-zA-A]{2,3}" http://www.google.com http://code.google.com
原理
[a-zA-Z0-9.]+ “+”表示应该出现多次

用awk实现head、tail和tac
实战演练
$ awk 'NR <=10' filename
模拟tail命令打印文件的后10行
$ awk '{ buffer[NR % 10] = $0;} END { for(i=1;i<11;i++){print buffur[i%10] } }' filename

文件切片与参数操作
替换变量内容中的部分文本
$ var="this is a line of text"
$ echo ${var/line/REPLACED}
"This is a REPLACED of text"

$name ${name%$1}$2 #${name%\.*} "%"号除去后缀名,只取文件名
${file_name#*.} 只留扩展名或后缀

生成子窜
${variable_name:start_positon:length}

最后一个字符索引记为-1,使用负数索引的话,必须将负数放入括号内,例如(-1)就是最后一个字符的索引

string={a..z}
echo ${string:(-2):2}
yz
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息