shell 杂记

shell 杂记主要记录shell使用的以下小技巧,及命令。

从给定的文件中查找最大数及最小数

问题

从下述文件中找到最大值机最小值并打印。

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@hadoop01 shell]# cat number.txt
158 252 6389
15

124
485 78
1 256
493
1249
-1393 85 63

145 863
[root@hadoop01 shell]#

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@hadoop01 shell]# cat number.txt | sed 's/ /\n/g' | grep -v '^$' | sort -nr | sed -n '1p;$p'
6389
-1393
[root@hadoop01 shell]#

```cmd
> 注:
> sed 's/ /\n/g' 作用是将空格替换为换行符,是一个数字占一行
> grep -v '^$' 作用是过滤空行
> sort -nr 作用是将每行数字倒序排序
> sed -n '1p;$p' 作用是输出第一行和最后一行

## find命令玩法

### 过滤指定类型的文件

```shell
# find . -maxdepth 1 -type f -name '*.txt'

过滤指定类型及大小的文件

1
# find . -maxdepth 1 -type f -size +50M -name '*.txt'

过滤10天以前的文件

1
# find . -maxdepth 1 -type f -mtime +10 -name '*.txt'

过滤最经10天的文件

1
# find . -maxdepth 1 -type f -mtime -10 -name '*.txt'

将匹配到的文件删除

1
2
# find . -maxdepth 1 -type f -mtime +30 -name '*.txt' -exec rm -rf {} \;
# find . -maxdepth 1 -type f -mtime +30 -name '*.txt' | xargs rm -rf {} \;

awk玩法

输出指定列的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@hadoop01 shell]# cat hosts
master 192.168.10.11
work1 192.168.10.12
work2 192.168.10.13

[root@hadoop01 shell]# cat hosts | awk '{print $2}'
192.168.10.11
192.168.10.12
192.168.10.13

[root@hadoop01 shell]# cat hosts | awk '{print "IP is " $2}'
IP is 192.168.10.11
IP is 192.168.10.12
IP is 192.168.10.13

[root@hadoop01 shell]# cat hosts | awk '{print $2}' | awk -F\. '{print "IP first section " $1}'
IP first section 192
IP first section 192
IP first section 192

注:
awk -F[sep] 该参数可重新指定列分割标识符

linux shell 中 %% *的含义

定义了一个变量:

1
file=/dir1/dir2/dir3/my.file.txt

可以用${ }分别替换得到不同的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
${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

${file:0:5}:提取最左边的 5 个字节:/dir1
${file:5:5}:提取第 5 个字节右边的连续5个字节:/dir2
也可以对变量值里的字符串作替换:
${file/dir/path}:将第一个dir 替换为path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部dir 替换为 path:/path1/path2/path3/my.file.txt

记忆的方法为:

#是 去掉左边(键盘上#在 $ 的左边)

%是去掉右边(键盘上% 在$ 的右边)

单一符号是最小匹配

两个符号是最大匹配

shell read 用法

read命令用于从标准输入中读取输入单行,并将读取的单行根据IFS变量分裂成多个字段,并将分割后的字段分别赋值给指定的变量列表var_name。第一个字段分配给第一个变量var_name1,第二个字段分配给第二个变量var_name2,依次到结束。如果指定的变量名少于字段数量,则多出的字段数量也同样分配给最后一个var_name,如果指定的变量命令多于字段数量,则多出的变量赋值为空。

如果没有指定任何var_name,则分割后的所有字段都存储在特定变量REPLY中。

1
usage: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]

参数说明

1
2
3
4
5
6
7
8
9
10
选项说明:
-a:将分裂后的字段依次存储到指定的数组中,存储的起始位置从数组的index=0开始。
-d:指定读取行的结束符号。默认结束符号为换行符。
-n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取。
-N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束。其中换行符或回车算一个字符。
-p:给出提示符。默认不支持"\n"换行,要换行需要特殊处理,见下文示例。例如,"-p 请输入密码:"
-r:禁止反斜线的转义功能。这意味着"\"会变成文本的一部分。
-s:静默模式。输入的内容不会回显在屏幕上。
-t:给出超时时间,在达到超时时间时,read退出并返回错误。也就是说不会读取任何内容,即使已经输入了一部分。-u:从给定文件描述符(fd=N)中读取数据。
-u:后面跟fd,从文件描述符中读入

将读取的内容分配给数组变量,从索引号0开始分配(-a)

1
2
3
4
5
6
7
8
9
10
[root@hadoop01 shell]# read -a arr
unit as one to tackle tough Blessings
[root@hadoop01 shell]# echo $arr
unit
[root@hadoop01 shell]# echo ${arr[0]}
unit
[root@hadoop01 shell]# echo ${arr[1]}
as
[root@hadoop01 shell]# echo ${arr[@]}
unit as one to tackle tough Blessings

指定读取行的结束符号,而不再使用换行符(-d)

1
2
3
4
5
6
[root@hadoop01 shell]# read -d q arr
what is you name q # 输入完尾部的"q",自动结束read

# 由于没有指定var_name,所以通过$REPLY变量查看read读取的行。
[root@hadoop01 shell]# echo $REPLY
what is you name

限制输入字符(-n or -N)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 长度为5时自动结束
[root@hadoop01 shell]# read -n 5 arr
abcde[root@hadoop01 shell]#
[root@hadoop01 shell]# echo $arr
abcde

# 长度不到5时按<Enter>结束
[root@hadoop01 shell]# read -n 5 arr
123
[root@hadoop01 shell]# echo $arr
123

# 严格模式(-N),长度必须为5
[root@hadoop01 shell]# read -N 5 arr
12
3
[root@hadoop01 shell]# echo $arr
12 3

给出输入提示(-p)

1
2
3
4
[root@hadoop01 shell]# read -p "Input your name: " NAME
Input your name: Jack
[root@hadoop01 shell]# echo $NAME
Jack

“-p”选项默认不带换行功能,且也不支持”\n”换行。但通过$’string’的方式特殊处理,就可以实现换行的功能。

1
2
3
[root@hadoop01 shell]# read -p $'Input your name: \n' NAME
Input your name:
Jack

禁止转义(-r)

1
2
3
4
5
[root@hadoop01 shell]# read -r
what is you name \?

[root@hadoop01 shell]# echo $REPLY
what is you name \?

不回显输入的字符(-s)

1
2
3
4
[root@hadoop01 shell]# read -sp "input password: "
input password: [root@hadoop01 shell]#
[root@hadoop01 shell]# echo $REPLY
123456

将读取的行分割后赋值给变量

1
2
3
4
[root@hadoop01 shell]# read year month day
2020 01 30
[root@hadoop01 shell]# echo $year-$month-$day
2020-01-30

shell for 循环

数字性循环

列表for循环.

1
2
3
4
5
6
7
8
9
#!/bin/bash

for ((i=1; i<=10; i++))
do
echo `expr $i \* 3 + 1`
# echo $(expr $i \* 3 + 1)
# echo (($i * 3 + 1))
# echo $[$i * 3 + 1]
done
1
2
3
4
5
6
#!/bin/bash

for i in $(seq 1 10)
do
echo $(expr $i \* 3 + 1)
done
1
2
3
4
5
6
#!/bin/bash

for i in {1..10..1}
do
echo $(expr $i \* 3 + 1)
done
1
2
3
#!/bin/bash

awk 'BEGIN{for(i=1; i<=10; i++) print i}'

不带列表for循环.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# pra_for.sh
#!/bin/bash

echo "number of arguments is $#"
echo "What you input is: "
for argument
do
echo "$argument"
done

# pra_for.sh a b c
a
b
c

字符性循环

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

list="rootfs usr data data2"
for i in $list;
do
echo $i is appoint
done

# result
rootfs is appoint
usr is appoint
data is appoint
data2 is appoint

路径查找.

1
2
3
4
5
6
#!/bin/bash

for file in /proc/*;
do
echo $file is file path \!
done
1
2
3
4
5
6
#!/bin/bash

for file in $(ls *.sh)
do
echo $file is file path \!
done

shell while 循环

shell until 循环

shell select 循环

select in 循环用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能。

Shell select in 循环的用法

1
2
3
4
select variable in value_list
do
statements
done

variable 表示变量,

value_list 表示取值列表,

in 是 Shell 中的关键字。

示例

1
2
3
4
5
6
7
#!/bin/bash

echo "What is your favourite OS?"
select name in "Linux" "Windows" "Mac OS" "UNIX" "Android"
do
echo "You have selected $name"
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/ksh

PS3="Please make a selection => "
select DRINK in tea cofee water juice appe all none
do
case $DRINK in
tea|cofee|water|all)
echo "Go to canteen"
;;
juice|appe)
echo "Available at home"
;;
none)
break
;;
*) echo "ERROR: Invalid selection"
;;
esac
done

Shell 循环控制break/continue

break

break语句用于终止整个循环的执行

语法:

1
2
break
break n # n指第n个封闭的循环退出

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break 2
else
echo "$var1 $var2"
fi
done
done

# result
1 0
1 5

continue

ontinue语句break命令类似,但它会导致当前迭代的循环退出,而不是整个循环。

这种参数是有用的,当一个错误已经发生,但你想尝试执行下一个循环迭代。

语法:

1
2
continue
continue n # 这里n指定第n个封闭循环 continue

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh

NUMS="1 2 3 4 5 6 7"

for NUM in $NUMS
do
Q=`expr $NUM % 2`
if [ $Q -eq 0 ]
then
echo "Number is an even number!!"
continue
fi
echo "Found odd number"
done

shell 几中专用修饰符

  • :- ,${variable:-word} 如果variable已经被设置了,且不为空,则代入它的置,否则代入word;
1
2
3
4
5
6
$ fruit=peach
$ echo ${fruit:-plum}
peach

$ echo ${newfruit:-apple}
apple
  • :+ , ${variable:+word}如果变量variable已被设置且值为非空,代入word值,否则什么也不代入,
1
2
3
4
5
6
$ foo=grapes
$ echo ${foo:+pears}
pears

$ echo $foo
$ grapes
  • := , ${variable:=word}如果variable已经被设置且不为空,则代入它的值,否则代入word,并且在后面variable始终为word的值。位置参量不能用这种方式赋值。
1
2
3
4
5
6
$ name=
$ echo ${name:=peter}
peter

$ echo $name
$ peter
  • :? , ${variable:?word} 如果变量variable已被设置值且为非空,就代入它的值,否则输出word并从shell中退出,如果有省略了word,就会显示信息:parameter null or not set.
1
2
echo ${namex:?"namex is undefined"}
namex: namex is undefined
  • ${variable:offset:length}

${variable:offset} 获得变量从variable值中位置从offset开始的子串,偏移为从0到串尾。
${variable:offset:length} 获得variable值位置从offset开始长度为length的子串。

1
2
3
4
5
6
$var=notebook
$ echo ${var:0:4}
note

$ echo ${var:4:4]
book
-------------本文结束感谢您的阅读-------------