shell study

2019/01/15 shell 服务器

shell记录

执行脚本

  • 作为可执行程序
chmod +x ./test.sh  #使脚本具有执行权限
./test.sh  #执行脚本
  • 作为解释器执行
    /bin/sh test.sh
    /bin/php test.php
    

变量使用

name='bob'
echo $name
echo "my name id $name"
echo "Hello,"$name"!"
echo ${#name}               #输出 4 (长度)

string="你本来就很帅"
echo "长度"${#string}
echo ${string:1:4}          #从第二个字符开始截取4个字符

echo `expr index "$string" 本来`  #查找字符本或来的位置(哪个字母先出现就计算哪个)

content="---
apiVersion: v1
kind: ConfigMap
metadata:
  name: $2
  namespace: bigdata"
`echo -e "${content}" >> ../configmap.yaml   # -e 开启转义 \n会换行

##shell数组
array_name=(value0 value1 value2 value3)
echo ${array_name[@]}                       #@获取数组所有元素
length=${#array_name[@]}                    #获取数组长度
echo $length
lengthn=${#array_name[2]}                   #获取第二个元素的长度
echo $lengthn

注释

#----------------------------------
# 这是一个注释
# author:walkingsun
#----------------------------------

# 多行注释
:<<EOF
注释内容...
注释内容...
注释内容...
EOF


:<<!
注释内容...
注释内容...
注释内容...
!

shell传递参数

#!/bin/bash

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";                       # $0 为执行的文件名
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

执行

./test.sh 1 2 3
参数处理	说明
$#	传递到脚本的参数个数
$*	以一个单字符串显示所有向脚本传递的参数。
如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$	脚本运行的当前进程ID号
$!	后台运行的最后一个进程的ID号
$@	与$*相同,但是使用时加引号,并在引号中返回每个参数。
如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$-	显示Shell使用的当前选项,与set命令功能相同。
$?	显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

$* 与 $@ 区别:

相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。

运算符

## 算数运算符
运算符	说明	举例
+	加法	`expr $a + $b` 结果为 30。
-	减法	`expr $a - $b` 结果为 -10*	乘法	`expr $a \* $b` 结果为  200。
/	除法	`expr $b / $a` 结果为 2。
%	取余	`expr $b % $a` 结果为 0。
=	赋值	a=$b 将把变量 b 的值赋给 a。
==	相等。用于比较两个数字,相同则返回 true[ $a == $b ] 返回 false!=	不相等。用于比较两个数字,不相同则返回 true[ $a != $b ] 返回 true## 关系运算符
-eq	检测两个数是否相等,相等返回 true[ $a -eq $b ] 返回 false-ne	检测两个数是否不相等,不相等返回 true[ $a -ne $b ] 返回 true-gt	检测左边的数是否大于右边的,如果是,则返回 true[ $a -gt $b ] 返回 false-lt	检测左边的数是否小于右边的,如果是,则返回 true[ $a -lt $b ] 返回 true-ge	检测左边的数是否大于等于右边的,如果是,则返回 true[ $a -ge $b ] 返回 false-le	检测左边的数是否小于等于右边的,如果是,则返回 true[ $a -le $b ] 返回 true## 布尔运算符
运算符	说明	举例
!	非运算,表达式为 true 则返回 false,否则返回 true[ ! false ] 返回 true-o	或运算,有一个表达式为 true 则返回 true[ $a -lt 20 -o $b -gt 100 ] 返回 true-a	与运算,两个表达式都为 true 才返回 true[ $a -lt 20 -a $b -gt 100 ] 返回 false## 逻辑运算符
&&	逻辑的 AND	[[ $a -lt 100 && $b -gt 100 ]] 返回 false
||	逻辑的 OR	[[ $a -lt 100 || $b -gt 100 ]] 返回 true

## 字符串运算符
=	检测两个字符串是否相等,相等返回 true[ $a = $b ] 返回 false!=	检测两个字符串是否相等,不相等返回 true[ $a != $b ] 返回 true-z	检测字符串长度是否为0,为0返回 true[ -z $a ] 返回 false-n	检测字符串长度是否为0,不为0返回 true[ -n "$a" ] 返回 true。
str	检测字符串是否为空,不为空返回 true[ $a ] 返回 true## 文件测试运算符

操作符	说明	举例
-b file	检测文件是否是块设备文件,如果是,则返回 true[ -b $file ] 返回 false-c file	检测文件是否是字符设备文件,如果是,则返回 true[ -c $file ] 返回 false-d file	检测文件是否是目录,如果是,则返回 true[ -d $file ] 返回 false-f file	检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true[ -f $file ] 返回 true-g file	检测文件是否设置了 SGID 位,如果是,则返回 true[ -g $file ] 返回 false-k file	检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true[ -k $file ] 返回 false-p file	检测文件是否是有名管道,如果是,则返回 true[ -p $file ] 返回 false-u file	检测文件是否设置了 SUID 位,如果是,则返回 true[ -u $file ] 返回 false-r file	检测文件是否可读,如果是,则返回 true[ -r $file ] 返回 true-w file	检测文件是否可写,如果是,则返回 true[ -w $file ] 返回 true-x file	检测文件是否可执行,如果是,则返回 true[ -x $file ] 返回 true-s file	检测文件是否为空(文件大小是否大于0),不为空返回 true[ -s $file ] 返回 true-e file	检测文件(包括目录)是否存在,如果是,则返回 true[ -e $file ] 返回 true

echo

echo -e "OK! \n" # -e 开启转义 \n显示换行

echo -e "OK! \c" # -e 开启转义 \c 不换行

echo "It is a test" > myfile                        #显示结果定向到文件

echo `date`                                         #显示命令执行结果

printf

printf  format-string  [arguments...]

模仿c程序库的printf(php也是如此)

printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4s\n" walkingsun boy 150
# %s %c %d %f都是格式替代符
# %-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
# %-4.2f 指格式化为小数,其中.2指保留2位小数。

test

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

# 数值测试
参数	说明
-eq	等于则为真
-ne	不等于则为真
-gt	大于则为真
-ge	大于等于则为真
-lt	小于则为真
-le	小于等于则为真


# 字符串测试
=	等于则为真
!=	不相等则为真
-z 字符串	字符串的长度为零则为真
-n 字符串	字符串的长度不为零则为真

# 文件测试
-e 文件名	如果文件存在则为真
-r 文件名	如果文件存在且可读则为真
-w 文件名	如果文件存在且可写则为真
-x 文件名	如果文件存在且可执行则为真
-s 文件名	如果文件存在且至少有一个字符则为真
-d 文件名	如果文件存在且为目录则为真
-f 文件名	如果文件存在且为普通文件则为真
-c 文件名	如果文件存在且为字符型特殊文件则为真
-b 文件名	如果文件存在且为块特殊文件则为真

流程控制

if … else …

if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi    # 查询进程中命令行包含ssh的数量是否大于1,是返回true   -c 统计数量

if … elseif …else … fi

if condition1
then
    command1
elif condition2
then
    command2
else
    commandN
fi

for

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

实例:

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

## 顺序输出字符串中的字符
for str in 'This is a string'
do
    echo $str
done

数字循环

#!/bin/bash  
  
for((i=1;i<=10;i++));  
do   
echo $(expr $i \* 3 + 1);  
done  

while

while condition
do
    command
done

实例:

#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

无限循环

while :
do
    command
done
或者

while true
do
    command
done
或者

for (( ; ; ))

until

until 循环
until 循环执行一系列命令直至条件为 true 时停止。

until 循环与 while 循环在处理方式上刚好相反。

一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

until 语法格式:

until condition
do
    command
done

case

casein
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

实例

echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac

跳出循环

break和continue (同PHP)

esac 需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break。

函数

[ function ] funname [()]

{

    action;

    [return int;]

}

实例:

funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"


# 传参
funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
#注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

注意


参数处理	说明
$#	传递到脚本的参数个数
$*	以一个单字符串显示所有向脚本传递的参数
$$	脚本运行的当前进程ID号
$!	后台运行的最后一个进程的ID号
$@$*相同,但是使用时加引号,并在引号中返回每个参数。
$-	显示Shell使用的当前选项,与set命令功能相同。
$?	显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

输入输出重定向


命令	说明
command > file	将输出重定向到 file。
command < file	将输入重定向到 file。
command >> file	将输出以追加的方式重定向到 file。
n > file	将文件描述符为 n 的文件重定向到 file。
n >> file	将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m	将输出文件 m 和 n 合并。
n <& m	将输入文件 m 和 n 合并。
<< tag	将开始标记 tag 和结束标记 tag 之间的内容作为输入。
cat file1 >> file 将file1内容输出已追加的形式重定向到 file

实例

 who > users   #执行 who 命令,它将命令的完整的输出重定向在用户文件中(users)

重定向深入

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息
command 2 > file    #stderr 重定向到 file

command 2 >> file   #stderr 追加到 file 文件末尾

command > file 2>&1   #stdout 和 stderr 合并后重定向到 file

command < file1 >file2  #stdin 和 stdout 都重定向,command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2

Here Document

command << delimiter
    document
delimiter

实例

在命令行中通过 wc -l 命令计算 Here Document 的行数:

$ wc -l << EOF
    欢迎来到
    菜鸟教程
    www.runoob.com
EOF

3          # 输出结果为 3 行
$

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出”的效果。

如果希望屏蔽 stdout 和 stderr, 以这样写:

$ command > /dev/null 2>&1

shell文件包含

. filename   # 注意点号(.)和文件名中间有一空格source filename

nohup 退出帐户/关闭终端之后继续运行相应的进程

nohup command > myout.file 2>&1 &

0 – stdin (standard input),1 – stdout (standard output),2 – stderr (standard error) ;
2>&1是将标准错误(2)重定向到标准输出(&1),标准输出(&1)再被重定向输入到myout.file文件中。

& : 指在后台运行

&是指在后台运行,但当用户推出(挂起)的时候,命令自动也跟着退出

sh test.sh &

使命令永久的在后台执行

nohup COMMAND &

Vim

:%s/\n//g    # 去除换行
%s/ //g			 # 去除空格

head/tail文本选取

head/tail是linux中常见的文本选取命令,用以选取头部/尾部的若干行文本

head: illegal option -- -
usage: head [-n lines | -c bytes] [file ...]
# 输出头部两行
head -n 2 configmap.yaml
# 输出匹配data的第一个数据
grep data configmap.yaml | head -1
# 输出尾部2行
tail -n 2 configmap.yaml
# 输出不断增长的日志文件
tail -f nginx.log

shell三剑客 grep、awk、sed

grep

基于正则表达式查找满足条件的内容

grep
grep [OPTIONS] PATTERN [FILE...]
-o 仅显示匹配到的字符串
-E 使用ERE,相当于egrep
--color=auto 对匹配到的文本着色显示
-v 显示不被pattern匹配到的行
-i 忽略字符大小写
-n 显示匹配的行号
-c 统计匹配的行数
-q 静默模式,不输出任何信息
-A # after, 后#行
-B # before, 前#行
-C # context, 前后各#行
-e 实现多个选项间的逻辑or关系
grep –e ‘cat ’ -e ‘dog’ file
-w 匹配整个单词
-F 相当于fgrep,不支持正则表达式

实例:

cat configmap.yaml |grep addr -n

更多参考正则表达式详解

sed

sed是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑,最后输出所有行活仅输出处理的某些行,sed可以在无交互的情况下实现相当复杂的文本处理操作。被广泛的应用于shell脚本中,用于完成各种自动化处理任务。

sed的工作流程主要包括:

  1. 读取:sed从输入流中读取一行内容不能够存储到临时的缓冲区中;
  2. 执行:默认情况下所有的sed命令都在模式空间中按顺序地执行,除非指定了行的地址,否则sed命令将会再所有行上依次执行;
  3. 显示:发送修改后的内容到输出流,再发送数据后,模式空间将会被清空。 注意:在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容都被处理完。
    sed [option]... 'script' inputfile
    1、选项
    -n 不输出模式空间内容到屏幕,即不自动打印
    -e 多点编辑
    -f /PATH/SCRIPT_FILE: 从指定文件中读取编辑脚本
    -r 支持使用扩展正则表达式
    -i 直接编辑文件
    -i.bak 备份文件并原处编辑
    2、script 地址定界
    不给地址:对全文进行处理
    单地址:
    #: 指定的行,$:最后一行
    /pattern/:被此处模式所能够匹配到的每一行
    地址范围:
    #,#
    #,+#
    /pat1/,/pat2/
    `#,/pat1/
    ~:步进
    1~2 奇数行
    2~2 偶数行
    3、编辑命令:
    d 删除模式空间匹配的行,并立即启用下一轮循环
    p 打印当前模式空间内容,追加到默认输出之后
    a []text1 在指定行后面追加文本,支持使用\n实现多行追加
    i []text 在行前面插入文本
    c []text 替换行为单行或多行文本
    w /path/somefile 保存模式匹配的行至指定文件
    r /path/somefile 读取指定文件的文本至模式空间中匹配到的行后
    = 为模式空间中的行打印行号
    ! 模式空间中匹配行取反处理
    s///:查找替换,支持使用其它分隔符,s@@@,s###
    

    用法

    • 输出符合条件的文本 ```shell

      输出所有内容,等同于“cat test.txt”

      sed -n ‘p’ test.txt

输出第三行

sed -n ‘3p’ test.txt

输出3-5 行

sed -n ‘3,5p’ test.txt

输出所有奇数行,n表示读入下一行数据

sed -n ‘p;n’ test.txt

输出所有偶数行,n表示读入下一行数据

sed -n ‘n;p’ test.txt

输出包含“the”的行

sed -n ‘/the/p’ test.txt

输出从第4行到都第一个包含“the”的行

sed -n ‘4,/the/p’ test.txt

输出包含“the”的行所在的行号(等号(=)用来输出行号)

sed -n ‘/the/=’ test.txt

输出以“PI”开头的行

sed -n ‘/^PI/p’ test.txt

输出包含单词wood的行,\<、\>代表单词边界

sed -n ‘/\<wood\>/p’ test.txt

- 删除符合条件的文本
nl命令用于计算文件的行数
```shell
# 删除第3行
nl test.txt | sed '3d'
# 删除第3-5行
nl test.txt | sed '3,5d'
# 删除包含cross的行,原本的第8行被删除
nl test.txt | sed '/cross/d'
# 删除不包含cross的行
nl test.txt | sed '/cross/! d'
# 删除以“.”结束的行
sed '/\.$/d' test.txt 
# 删除所有空行
sed '/^$/d' test.txt 
# 删除空行,连续的空行留一个
sed -e '/^$/{n;/^$/d}' test.txt
  • 替换符合条件的文本 使用sed命令进行替换操作时需要用到的选项:s(字符串替换)、c(整行整块替换)、y(字符转换)等命令选项。 ```shell [root@localhost ~]# sed ‘s/the/THE/’ test.txt //将每行中的第一个the替换为THE [root@localhost ~]# sed ‘s/l/L/2’ test.txt //将每行中的第三个“l”替换为“L” [root@localhost ~]# sed ‘s/the/THE/g’ test.txt //将文件中所有的“the”替换为“THE” [root@localhost ~]# sed ‘s/o//g’ test.txt //将文件中所有的“o”删除 [root@localhost ~]# sed ‘s/^/#/’ test.txt //在每行的行首插入“#”号 [root@localhost ~]# sed ‘/the/s/^/#/’ test.txt //在包含“the”的每行行首插入“#”号 [root@localhost ~]# sed ‘s/$/EOF/’ test.txt //在每行行尾插入字符串“EOF” [root@localhost ~]# sed ‘3,5s/the/THE/g’ test.txt //将第3~5行中的所有“the”替换为“THE” [root@localhost ~]# sed ‘/the/s/o/O/g’ test.txt //将包含“the”的所有行中的o替换为“O”

“sed -i”的命令则是立即生效的!

[root@localhost ~]# sed -i ‘1c 1111’ a.txt //替换文中第一行的内容为“1111” [root@localhost ~]# sed -i ‘1a 1111’ a.txt //在第一行后面插入一行内容,内容为“1111” [root@localhost ~]# sed -i ‘1i 2222’ a.txt //在第一行前面插入一行内容,内容为“2222” [root@localhost ~]# sed -i ‘1d’ a.txt //删除第一行内容 sed -n “1,10p” // 删除1到10行内容
[root@localhost ~]# sed -n ‘1p’ a.txt //打印出第一行的内容 [root@localhost ~]# sed -i ‘1s/2222/3333/g’ a.txt //将文本第一行内容“2222”替换为“3333”

- 迁移符合条件的文本
使用sed命令进行迁移文本操作时需要用到的选项有:g、G将剪贴板中的数据覆盖/追加到指定行;w保存为文件;r读取指定文件;a追加指定内容。
```shell
[root@localhost ~]# sed '/the/{H;d};$G' test.txt 
//将包含“the”的行迁移到文件末尾,“;”用于多个操作
[root@localhost ~]# sed '1,5{H;d};17G' test.txt 
//将第1~5行的内容转移到第17行后
[root@localhost ~]# sed '/the/w out.file' test.txt 
//将包含“the”的行另存为文件out.file
[root@localhost ~]# sed '/the/r /etc/hostname' test.txt 
//将文件/etc/hostname的内容添加到包含“the”的每行以后
[root@localhost ~]# sed '3aNEW' test.txt 
//在第3行后面插入一个新行,内容为“NEW”
[root@localhost ~]# sed '/the/aNEW' test.txt 
//在包含“the”的每行后插入一个新行,内容为“NEW”
[root@localhost ~]# sed '3aNEW1\nNEW2' test.txt
//在第3行后面多行内容,中间的“\n”表示换行

awk

报告生成器,格式化文本输出

Linux/UNIX系统中,awk是一个功能强大的编辑工具,逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的文本操作,被广泛应用于Shell脚本,完成各种自动化配置任务。

awk [options] 'program' file…
  • program:pattern{action statements;..}
    • pattern部分决定动作语句何时触发及触发事件 BEGIN,END
    • action statements对数据进行处理,放在{}内指明 print, printf
        awk '{print "  "$0}' file # 文件内容每行加空格输出
      
      awk  -f  脚本文件 文件1 文件2 …
      //从脚本中调用编辑指令,过滤并输出内容
      

      awk从输入文件或者标准输入中读入信息,与sed一样,信息的读入也是逐行读取的。不同的是,awk命令将文本文件中的一行视为一个记录,而将一行中的某一部分(列)作为记录的一个字段。为了操作这些不同的字段(列),awk借用shell中类似于位置变量的方法,用$1、$2…$9顺序的表示不同列,$0表示整行。不同字段与不同字段可以通过指定的方式进行分隔,awk默认的分隔符是空格。awk命令允许使用“-F分隔符”的形式来指定分隔符。

      # 打印 以:分隔的 第一个、第三个、第四个元素
      awk -F ':' '{print $1,$3,$4}' /etc/passwd
      

      awk内置变量: image

      用法

  • 按行输出文本
    [root@localhost ~]# awk '{print}' test.txt 
    //输出所有内容,等同于“cat test.txt”
    [root@localhost ~]# awk '{print $0}' test.txt
    //输出所有内容,等同于“cat test.txt”
    [root@localhost ~]# awk 'NR==1,NR==3{print}' test.txt 
    //输出第1~3行的内容
    [root@localhost ~]# awk '(NR&gt;=1) && (NR&lt;=3) {print}' test.txt 
    //输出第1~3行的内容
    [root@localhost ~]# awk 'NR==1 || NR==3{print}' test.txt 
    //输出第1行、第3行的内容
    [root@localhost ~]# awk '(NR%2)==1 {print}' test.txt 
    //输出所有奇数行的内容
    [root@localhost ~]# awk '(NR%2)==0 {print}' test.txt 
    //输出所有偶数行的内容
    [root@localhost ~]# awk '/^root/{print}' /etc/passwd
    //输出以“root”开头的行
    [root@localhost ~]# awk '/nologin$/{print}' /etc/passwd
    //输出以“nologin”结尾的行
    [root@localhost ~]# awk 'BEGIN {x=0} ;/\/bin\/bash$/{x++};END {print x}' /etc/passwd
    //统计以/bin/bash结尾的行数
    [root@localhost ~]# grep -c "/bin/bash$" /etc/passwd
    //统计以/bin/bash结尾的行数
    [root@localhost ~]# awk 'BEGIN{RS=""}; END{print NR}' /etc/squid/squid.conf
    //统计以空格分隔的文件段落数
    

    注意:命令较多时,使用“BEGIN……END”

  • 按字段输出文本
    [root@localhost ~]# awk '{print $3}' test.txt 
    //输出每行中(以空格分隔)的第3个字段
    [root@localhost ~]# awk '{print $1,$3}' test.txt 
    //输出每行中(以空格分隔)的第1个和第3个字段
    [root@localhost ~]# awk -F ":" '$2==""{print}' /etc/shadow
    //输出/etc/shadow文件中(以“:”分隔)的第二个字段(密码为空的用户)
    [root@localhost ~]# awk 'BEGIN {FS=":"}; $2=""{print}' /etc/shadow
    //输出/etc/shadow文件中(以“:”分隔)的第二个字段(密码为空的用户)
    [root@localhost ~]# awk -F ":" '$7~"/bash"{print $1}' /etc/passwd
    //输出以“:”分隔且第7个字段中包含“/bash”的行的第1个字段
    [root@localhost ~]# awk '($1~"nfs") && (NF==8) {print $1,$2}' /etc/services
    //输出包含8个字段且第1个字段中包含“nfs”的行的第1、2个字段
    [root@localhost ~]# awk -F ":" '($7!="/bin/bash") && ($7!="/sbin/nologin") {print}' /etc/passwd
    //输出第7个字段既不为“/bin/bash”也不为“/bin/nologin”的所有行
    
  • 通过管道,双引号调用Shell命令
    [root@localhost ~]# awk -F: '/bash$/{print | "wc -l"}' /etc/passwd
    //调用“wc -l”命令统计使用“bash”的用户个数
    [root@localhost ~]# grep -c "bash$" /etc/passwd
    //同上一条命令一样的作用
    [root@localhost ~]# awk 'BEGIN {while ("w" | getline) n++ ; {print n-2}}'
    //调用“w”命令,并用力啊统计在线用户数
    [root@localhost ~]# awk 'BEGIN { "hostname" | getline ; print $0}'
    //调用“hostname”命令,并输出当前用户名
    
  • 使用awk命令进行简单的数学运算
    [root@localhost ~]# awk 'BEGIN{ a=6;b=3;print"(a + b)=",(a + b)}'
    (a + b)= 9
    [root@localhost ~]# awk 'BEGIN{ a=6;b=3;print"(a - b)=",(a - b)}'
    (a - b)= 3
    [root@localhost ~]# awk 'BEGIN{ a=6;b=3;print"(a / b)=",(a / b)}'
    (a / b)= 2
    [root@localhost ~]# awk 'BEGIN{ a=6;b=3;print"(a % b)=",(a % b)}'
    (a % b)= 0
    

    tr

    tr主要用于将从标准输入读取的数据进行结果集映射、字符压缩和字符删除。它首先会将读取的标准输入进行排序然后按照某种方式换行,然后再根据给出的命令行参数做相关处理。

tr [options] [SET1] [SET2]

-c:使用SET1的补集 -d:删除字符 -s:压缩字符 -t:截断SET1,使得SET1的长度和SET2的长度相同

用法

tr '\n' , < 1.txt  # 文本中的换行符替换逗号

https://www.cnblogs.com/f-ck-need-u/p/7521506.html

解压

# 解压缩直接覆盖目标目录(已存在目录文件不会覆盖,只会覆盖相同的文件、文件夹)
tar zxvf /home/httpd/flow/new-media-stat.tgz -C /opt/case/new-media-stat

实践

这里会记录典型的shell应用场景

系统日志太多,占空间,想清理掉一个月之前的日志,只保留近期一个月的日志

#!/bin/sh
# 清理日志
# author:walkingsun
# test

path=/data/app/WindBlog/runtime/logs/                   #指定清理目录
timeout=`expr 30 \* 86400`                              #过期时间(当前设为30天)
systime=`date +%s`                                      #获取当前系统的时间 (秒为单位)

files=$(ls $path)
for filename in $files
do
  fileuptime=`stat -c %Y $path$filename`                #获取文件修改时间(秒)
  if [ $[ $systime - $fileuptime ] -gt $timeout ]
  then
     echo $path$filename
     echo `rm -rf $apth$filename`
  fi
done

给定一个文件 file.txt,转置它的内容。

你可以假设每行列数相同,并且每个字段由 ‘ ‘ 分隔.

示例:

    假设 file.txt 文件内容如下:
    
    name age
    alice 21
    ryan 30
    应当输出:
    
    name alice ryan
    age 21 30

解答

#!/bin/bash

awk '{for(i=1;i<=NF;i++){if(NR==1){data[i]=$i}else{data[i]=data[i]" "$i}}}END{for(i=1;i<=NF;i++) print data[i]}' file.txt

给定一个包含电话号码列表(一行一个电话号码)的文本文件 file.txt,写一个 bash 脚本输出所有有效的电话号码。

你可以假设一个有效的电话号码必须满足以下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)

你也可以假设每行前后没有多余的空格字符。

示例:

假设 file.txt 内容如下:

987-123-4567

123 456 7890

(123) 456-7890

你的脚本应当输出下列有效的电话号码:

987-123-4567

(123) 456-7890

#!/bin/bash

awk '/^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$/{print $0}' file.txt

写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率。

    为了简单起见,你可以假设:
    
    words.txt只包括小写字母和 ' ' 。
    每个单词只由小写字母组成。
    单词间由一个或多个空格字符分隔。
    示例:
    
    假设 words.txt 内容如下:
    
    the day is sunny the the
    the sunny is is
    你的脚本应当输出(以词频降序排列):
    
    the 4
    is 3
    sunny 2
    day 1
#!/bin/bash

awk '{for(i=1;i<=NF;i++){a[$i]=a[$i]+1}}END{for(k in a){print k" "a[k]}}' words.txt |sort -nr -k 2

分表1024张,生成sql脚本

文件 db.sh

#!/bin/bash
start=$1
end=$2
file=$3
echo '' > $file
#for y in {$start..$end};do
for((i=$start;i<$end;i++));do
str=" create table reader_free_click_$i(\n
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n
\`adid\` varchar(32) NOT NULL DEFAULT '' COMMENT '广告计划id',\n
\`cid\` varchar(100) NOT NULL DEFAULT '' COMMENT '广告创意id',\n
\`imei_md5\` char(32) NOT NULL DEFAULT '' COMMENT '安卓设备识别码的md5',\n
\`mac\` char(32) NOT NULL DEFAULT '' COMMENT 'MAC地址的md5sum',\n
\`androidid\` varchar(40) DEFAULT NULL,\n
\`client_ip\` varchar(40) DEFAULT NULL,\n
\`source\` varchar(32) NOT NULL DEFAULT '' COMMENT '媒体来源',\n
\`timestamp\` bigint(18) NOT NULL DEFAULT '0' COMMENT '点击时间',\n
\`callback\` varchar(2048) NOT NULL DEFAULT '' COMMENT '回调参数',\n
\`channel\` varchar(40) DEFAULT NULL COMMENT '渠道唯一标示',\n
\`change_flag\` tinyint(1) NOT NULL DEFAULT '0' COMMENT '渠道是否变更(0:没有变更; 1:变更过)',\n
\`old_channel\` varchar(50) NOT NULL DEFAULT '' COMMENT '原始日志的渠道名',\n
\`book_id\` int(11) DEFAULT '0',\n
\`created_at\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入日期',\n
PRIMARY KEY (\`id\`),\n
UNIQUE KEY \`uk_its\` (\`imei_md5\`,\`timestamp\`,\`source\`)\n
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='免费小说媒体点击数据';\n\n";
echo $str >> $file
done

执行:

sh  db.sh 0 1023 db.sql

Search

    Table of Contents