shell简单语法

shell 相关

通配符

  • '*':匹配0个或者多个
  • '?':匹配任意单个字符串
    • ls -l file?.txt 这种情况下 file10.txt 就不会被匹配出来
  • [list] :匹配list当中的任意单个字符串
    • ls -l file[1-10].txt ---> file1.txt,file0.txt,逻辑:匹配单个字符串 file[1-1].txt file[0].txt
    • ll file[1-2,10,11].txt ---> file0.txt file1.txt file2.txt 如果有,.txt也会匹配出来
  • [!list]:匹配除list中的任意单个字符串
  • {string1,string2} 匹配 string1 string2 或者更多字符串
    • ll file{5..9}.txt ---> file5.txt,file6.txt,file7.txt,file8.txt,file9.txt

引号

  • 双引号 :会把引号的内容当做整体来看待,允许通过$符号引用其他变量值
  • 单引号:会把引号的内容当做整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
  • 反撇号:反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用
  • echo $(date) ---> 2020年 5月 2日 星期六 12时10分27秒 CST
  • echo "$(date)" ---> 2020年 5月 2日 星期六 12时10分44秒 CST
  • echo '(date)' --->(date)
  • echo "date" ---> 2020年 5月 2日 星期六 12时12分30秒 CST

变量

基本用法

➜  shell命令学习 A=hello    # 定义
➜  shell命令学习 echo $A    # $A 表示变量
hello
➜  shell命令学习 echo ${A}  # ${A} 表示变量
hello
➜  shell命令学习 echo ${A:1:3}  # 从第一个字符开始,截取三个
ell
➜  shell命令学习 unset A    # 重置A,释放变量A

➜  shell命令学习 B=$(hostname) # 将命令的输出结果赋值给某个变量
➜  shell命令学习 echo $B
dingdeMacBook-Pro.local
  • 变量名规则:区分大小写,不要有特殊字符,不能以数字开头,等号两边不能有任何空格

  • 使用方式:A{A}

  • 类型声明:

    • declare -i B=123 -i 将变量声明成整数
    • declare -r C=hello -r 将变量声明为只读,不能再次修改,如果修改的话,会报错,可以exit结束这个变量,生命周期就会结束
    • declare -x D=hello -x 将变量通过环境导出,与export一样
  • 变量分类

    • 本地变量,只对当前进程有效

    • 环境变量,当前进程有效,并且能够被子进程调用

      • env 查看当前用户的环境变量
      • set 查看当前用户的所有变量(临时变量+环境变量) set|grep path
      • export 变量名=变量值
    • 全局变量,所有用户和进程都能调用,且继承,新建的用户也默认能调用

      • ~/.bashrc 当前用户的bash信息,用户登录时读取。只是针对用户。一般用于定义别名,umask,函数等
      • ~/.bash_profile 当前用户的环境变量,用户登录时读取。
      • ~/.bash_logout 当前用户退出当前shell时最后读取
      • /etc/profile 全局环境变量
      • /etc/bashrc 全局bash信息,所有用户生效
      • 读取顺序 /etc/profile ==> ~/.bash_profile ==> ~/.bashrc ==> /etc/bashrc ==> ~/.bash_logout
    • 系统变量

      命令 上一个命令或函数的返回码,0-正常
      $0 当前执行的程序或者脚本名,一般在某个脚本中,获取自身文件名
      $# 脚本后面接的参数的个数
      $* 脚本后面所有的参数。每个变量参数之间以空格隔开
      $@ 脚本后面所有的参数。参数是对立的,也是全部输出
      1 -9 脚本后面的位置参数,$1 表示第一个位置参数
      {10} -{n} 扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上括起来)
      $$ 当前所在的进程的进程号
      $! 后台运行的最后一个进程号
      !$ 调用最后一条命令历史中的参数
      $? 上一个命令或函数的返回码,0-正常

四则运算

表达式 示例
$(()) echo $((1 + 10)) ==> 11
$[] echo $[1+10] ==> 11
expr expr 1 + 10 ==> 11 这里需要有空格,不能用括号,乘法的话要加转义符 expr 2 * 10
let n=2;let n=n+10;echo $n; let n=n**3 n的3次方

条件判断语句

语法

  • test 条件表达式
  • [ 条件表达式 ] 注意,[] 里面有空格
  • [[ 条件表达式 ]] 支持正则表达式,注意,[] 里面有空格
  • [ ! 条件表达式 ] 取返表达式

判断文件类型

判断参数 含义
-e 文件是否存在
-f 文件是否存在并且是一个普通文件
-d 文件是否存在并且是一个目录
-L 文件是否存在并且是一个软连接文件
-r 文件是否存在并且是一个可读的文件
-w 文件是否存在并且是一个可写的文件
-x 文件是否存在并且是一个可执行的文件
-O 文件是否存在并且属于有效用户ID
-G 文件是否存在并且属有效用户组
-s 文件是否存在并且是一个非空文件
file1 -nt file2 比较file1是否比file2新
file1 -ot file2 比较file1是否比file2旧
file1 -et file2 比较是否为同一个文件,或者用于判断硬连接是否指向一个inode

判断字符串

判断参数 含义
-z 是否为空字符串,字符串长度为0则成立
-n 是否为非空字符串,字符串长度不为0则成立
s1 = s2 字符串是否相等;注意等号两边有空格;[ "A" = "B" ]
s1 != s2 字符串是否不相等;注意等号两边有空格;
[ $sting ] 字符串是为非空,和-n类似

判断整数

判断参数 含义
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于

多重条件判断

判断符号 含义 举例
-a 和 && 逻辑与 [ 1 -eq 1 -a 1 -ne 0 ] [ 1 -eq 1 ] && [ 1 -ne 0 ]
-o 和 || 逻辑或 [ 1 -eq 1 -o 1 -ne 0 ] [ 1 -eq 1 ] || [ 1 -ne 0 ]

这里有个优先级的问题

[ $(id -u) -eq 0 ] && echo "is admin" || echo "is not admin"

上面的话,输出为 is not admin,&& 如果前面的条件不满足,就不会执行后面了,|| 如果前面的条件不满足,就会执行后面

类C风格的数值比较

在(( ))中 判断

(( 1==1 ));echo $?
(( 1<=2 ));echo $?
(( 2!=3 ));echo $?

注意点

[ ] 和 [[ ]],有什么区别?

A=
[ $A = hello ] # 这一行会报错
# 下面一行不会报错,我们写字符串判断的时候,可以这么写;
# 这里还要注意,$A不能使用单引号引起来
[ "$A" = "hello" ]
# 使用[[  ]] 也不会报错
[[ $A = hello ]]

# 下面这句话会报错
[ 1 -eq 1 && 1 -eq 0 ]
# 使用[[  ]]后,不会报错了
[[ 1 -eq 1 && 1 -eq 0 ]]

if语句

if []; then
    命令
elif []; then
    命令
else
    命令
if

循环

for循环

for variable in {list}
do
    command
done
# 使用可选列表
for i in a b c;do echo "$i";done 
# 使用 seq
for i in $(seq 10); do echo $i ;done
# 使用 seq 从1开始,到10,每次加2
for i in $(seq 1 2 10); do echo $i ;done
# 类C风格
for (( i=0;i<5;i++ ));do echo $i;done
# 这种方式可以让用户通过参数的形式来自定义数量,for i in '"$@"'
for i;do echo $i;done

##########
for i in {1..5}
do
    echo "$i"
done

并发执行:

{程序}& 表示将程序放到后台并执行,如果需要等待程序执行完毕再进行下面内容,需要加wait

for ((i=1;i<=100;i+=2 ))
do {
    echo "hello"
}&
done
wait
echo "输出完毕"

while循环

while 表达式
do
    command
done
# while true
i=1
while (($i<=5))
do
    echo $i
    let i++
done

until循环

until 表达式
do
    command
done
# until false

i=1;
until (($i>5));
do 
    echo $i;
    let i++;
done

随机数

# (0-32767)
echo $RANDOM
# 0-9的随机数,取余
echo $[$RANDOM%10]
# 100 - 999
echo $[$RANDOM%900+100]

shift

使位置参数向左移动,默认移动1位,可以使用 shift 2 移动两位

sum=0
# $# 参数列表
while [ $# -ne 0 ]
do
    let sum=$sum+$1
    # 将参数位置先左移动1位  此时 $1 取出来的值为当前的那个参数
    shift
done
echo $sum

expect

expect 自动应答,tcl语言,例如远程登录,需要输入密码,expect就可以做到

数组

普通数组

一次赋予一个值

# 数组名[索引下标]=值
array[0]=v1
array[1]=v2

一次赋予多个值

# 数组名=(值1 值2 值3 ...)  空格隔开
array=(var1 var2 var3)
array1=(`cat /etc/passwd`) # 将文件中每一行赋值给array1数组
array2=(`ls /root`)
array3=(1 2 3 4 "hello world" [10]=linux)

数组读取

${数组名[元素下标]}
echo ${array1[0]}  # 数组中的第0个元素
echo ${array1[*]}  # 数组里的所有元素
echo ${array1[@]}  # 数组里的所有元素
echo ${array1[*]:1:100}  # 访问指定的元素;1代表下标从1的元素开始获取,100 代表后面获取几个元素
echo ${#array1[*]}  # 获取数组中所有元素的个数
echo ${!array1[*]}  # 获取数组元素的索引下标

关联数组

赋值

declare -A a_array1
a_array1[linux]=5

declare -A a_array2=(["hh"]="3" [kk]="4")

取值

echo ${a_array1[C]}
echo ${a_array1[*]}  # 所有的value
echo ${!a_array1[*]}  # 所有的key

case

case $1 in             
    start|S)               # 如果是 start 或者是 S
    echo "is start..."     # 执行语句
    ;;                     # 两个分好,命令结束
    stop|T)
    echo "is stop..."
    ;;
    *)                     # default 不满足上面的模式,执行*)下面的语句
    echo "请输入些什么吧..."
esac                       # case 语句结束

函数

定义

函数名()
{
    函数体
}

function 函数名()
{
    函数体
}

return 的作用

  • 结束一个函数
  • return 默认返回最后一个命令状态值,也可以给定参数值,范围是0-256
  • 如果没有return 命令,函数将返回最后一个指令的退出状态值

调用函数

source xxx.sh
# 直接使用方法名调用
hello

传参

hello()
{
    echo "hello $1"
}

正则表达式

相关概念

  • 元字符:值那些在正则表达式中具有特殊意义的专用字符,如 . * ?
  • 前导字符:位于元字符前面的字符 abc*(c为前导字符)

元字符

元字符 功能 备注
. 匹配除类换行符意外的任意单个字符
* 前导字符 出现0次 或者多次
.* 任意长度字符 abc.*
^ 行首(以...开头) ^root
$ 行尾(以...结尾) bash$
^$ 空行
[] 匹配括号里任意单个字符或一组单个字符 [abc] 包括a或者b或者c
[^] 匹配不包括括号里任一单个字符或一组单个字符 [^abc] 不包括a或者b或者c
^[] 匹配以括号里任意单个字符或一组单个字符开头 ^[abc] 以a或者b或者c开头
[] 匹配不以括号里任意单个字符或一组单个字符开头
\< 取单词的头 \<hel 以hel开头
\> 取单词的尾
\< \> 精确匹配 \<hello\> 精确匹配hello单词
\{n\} 匹配前导字符 连续出现n次 go\{2\},o连续出现2次 goo。[0-9]\{2\} 两位数字
\{n,\} 匹配前导字符 至少出现n次 go\{2,\},o至少出现2次 go,goo,gooo
\{n,m\} 匹配前导字符 出现n次到m次之间 go\{2,4\},o出现2-4次 goo,gooo,gooo
\( \) 保存被匹配的字符
\d 匹配数字 (grep -P) [0-9]
\w 匹配字母数字下划线 (grep -P) [a-zA-Z0-9_]
\s 匹配空格、制表符、换页符 (grep -P) [\t\r\n]

扩展类正则

需要注意

  • grep 需要用 -E 或者 egrep
  • sed 需要加 -f
扩展元字符 功能 备注
+ 匹配一个或多个前导字符 bo+ 匹配boo、bo
? 匹配零个或一个前导字符 bo? 匹配bo、b
| a|b 匹配a或者b
() 组字符(看成整体) (a|b)c:便是匹配ac或则bc
{n} 前导字符重复n次
{n,} 前导字符重复至少n次
{n,m} 前导字符重复n到m次

sed

常见的语法格式有两种。一种是命令行模式,另外一种是脚本模式

1、命令行模式(参考网址

sed [option] '处理动作' 文件名

常用选项

选项 说明 备注
-e 进行多项(多次)编辑
-n 取消默认输出 不自动打印模式空间
-r 使用扩展正则表达式
-i 原地编辑(修改源文件) 慎用
-f 指定sed脚本的文件名

常见处理动作

动作 说明 备注
'p' 打印
'i' 在指定行之前插入内容 类似vim里的大写O
'a' 在指定行之后插入内容 类似vim里的小写o
'c' 替换指定行所有内容
'd' 删除指定行

举个例子

sed -n 'p' pass.txt # 打印每一行
sed -n '2p' pass.txt # 打印第2行
sed -n '1,5p' pass.txt # 打印第1-5行
sed -n '$p' pass.txt # 打印最后一行

sed 'ihello' pass.txt # 在每一行插入hello
sed '2,3ihello' pass.txt # 在第2行和第3行前面插入 hello
sed '2,3ahello' pass.txt # 在第2行和第3行后面插入 hello

# 注意,mac系统中需要添加\n
sed  "5i\\"$'\n'"helloworld" pass.txt
sed  '5i\'$'\n''helloworld' pass.txt

# 替换
sed '2,5cChina' pass.txt
sed '2,5c\'$'\n''China' pass.txt # mac 中的操作

# 删除
sed '1d' pass.txt #删除第一行
sed '/^helloworld/d' pass.txt #删除正则匹配到的那一行
sed '/^#/d' pass.txt

sed -ne '/root/p' -ne '/root/=' pass.txt# 先找出root关键字的行,然后在打印包含root关键字的行号
sed -ne '1p;5p' pass.txt # 打印第1行和第5行 
sed -e '/^#/d' -e '/^$/d' pass.txt # 删除#和空格的行
sed -r '/^#|^$/d' pass.txt # 删除#和空格的行
sed -i '1d' pass.txt #删除第一行,直接修改了文件 

搜索替换

# sed 选项 's/搜索的内容/替换的内容/p' 需要处理的文件
sed -n 's/root/ROOT/gp' 1.txt # gp为全局替换
sed -n 's/^#//gp' 1.txt # 将行首的#替换为空格(去掉行首#)
sed -n '1,5s/^/#/p' pass.txt # 1-5行首添加 #
sed -n 's@/root@/ROOT/gp' 1.txt # 这样写也是可以的

其他动作

动作 说明 备注
r 从另外文件中读取内容
w 内容另存为
& 保存查找串以便在替换串中引用 类似vim里的小写o
= 打印行号
! 对所选行意外的所有行应用命令,放到行数之后
q 退出
sed '3r /etc/hosts/' 1.txt # 读取hosts文件到1.txt的第三行,如果不表明行号的话,则在1.txt文件中,每一行都会插入hosts文件的内容
sed '1,5w 11.txt' 1.txt # 将1.txt中的1-5行,写入11.txt文件中
sed -n 's/^sync/#&/gp' 1.txt # 在以sync开头的哪一行的行首添加#
sed -n '/root/=' 1.txt # 打印包含root关键字的行号
sed -n '$=' pass.txt # 打印最后一样的行号
sed -n '1,5!p' 1.txt  # 打印不包含1-5行的所有内容

结合正则表达式

sed 选项 'sed命令或者正则表达式或者地址定位' 文件名

正则 说明 备注
/key/ 查询包含关键字的行 sed -n '/root/p' 1.txt
/key1/,/key2/ 匹配包含两个关键字之间的行 sed -n '/root/./mysql/p' 1.txt
/key/,x 从匹配关键字的行开始到文件的第x行之间的行(包含关键字所在的行) sed -n '/^root/,7p' 1.txt
x,/key/ 从第x行开始到与关键字的匹配行之间的行
x,y! 不包含 x到y 行
/key/! 不包含关键字的行 sed -n '/root/!p' 1.txt
sed -nr '3,/^aa|^yy/p' # 打印从第三行到 以aa开头或者以yy开头 的行

脚本模式

# sed -f scripts.sh file # 使用脚本处理文件

# 脚本的第一行
#!/bin/sed -f
1,5d # 删除1-5行
s/root/hello/g # 将hello 替换成 hello
3i7777 # 在第三行添加 7777

注意:

  • 脚本文件是一个sed的命令行清单 'commands'
  • 在每行的末尾不能有任何空格、制表符(Tab) 或者饿其他文本
  • 如果在一行中有多个命令,应该使用分号隔开
  • 不需要且不可以使用引号做命令符
  • 号开头的行为注释

AWK

1、简介

awk 主要是对文本和数据进行处理,他处理文本和数据的方式:逐行扫描,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行想要的操作

2、使用方式

命令模式

1、语法结构

awk 选项 '命令部分' 文件名
# 引用shell变量需要使用双引号引起来

2、常用选项

  • -F 定义字段分割符号,默认是空格
  • -v 定义变量并赋值

3、命令部分

  • 正则表达式,地址定位
'/root/{awk语句}'   # sed中  '/root/p'
'NR=1,NR=5{awk语句}' # sed中 '1,5p'
'/^root/,/^root/{awk语句}' # sed中 '/^root/,/^ftp/p'
  • {awk语句;awk语句2;...} 注意中间是分号
'{print $0;print $1}' # sed中 'p'
'NR=5{print $0}' # sed中 '5p'
# 注意:awk命令语句间用分号隔开
  • BEGIN...END... 处理之前可以做些事情,处理之后可以做些事情
'BEGIN{awk语句};{处理中};END{awk语句}' # 拦截处理中的钩子 
'BEGIN{awk语句};{处理中}'
'{处理中};END{awk语句}'
脚本模式

1、脚本编写

#!/bin/awk -f   定义魔法字符
# 下面是awk引号里的命令清单,不要用引号保护命令,多个命令用分号分割
BEGIN{FS=":"}
NR==1,NR==3{print $1"\t"$NF}
...

2、脚本执行

# 方法1
awk 选项  -f awk的脚本文件 要处理的文本文件
awk -f awk.sh fileName

sed -f sed.sh -i filename

# 方法2
./awk的脚本文件(或者绝对路径) 要处理的文本文件
./awk.sh filename
./sed.sh filename

3、awk内部相关变量

变量 变量说明 备注
$0 当前处理行的所有记录
1,2,3...n 文件中每行以间隔符号分割的不同字段 awk -F: '{print 1,2}' 1.txt
NF 当前记录的字段数(列数) awk -F: '{print NF}' 1.txt
$NF 最后一列内容 $(NF-1)表示倒数第二列
FNR/NR 行号 awk -F: '{print NR}' 1.txt
FS 定义间隔符 BEGIN{FS=:};{print 1,3}
OFS 定义输出字段分割符,默认空格 BEGIN{OFS=:};{print 1,3}
RS 输入记录分割符,默认换行 BEGIN{RS="\t"};{print $0}
ORS 输出记录分隔符,默认换行
FILENAME 当前输入的文件名

相关命令举例

awk 'NR==1,NR==5{print $0}' 1.txt # 第一行到第五行
awk 'NR==1||NR==5||/root/{print $0}' 1.txt # 第一行或者第五行.或者包含root的行
awk 'NR>=1&&NR<=5{print $0}' 1.txt # 使用< 或 >
awk 'NR==1,NR==5;/^root/{print $0}' 1.txt # 这里是两个动作,满足/^root/的行会打印两次
awk -F: '/root/' 1.txt # 用:分割,包含root的行
awk -F: '/root/{print $0}' 1.txt # 和上面的等价
awk -F: '/^root/,NR==10{print $0}' 1.txt # 从以root开头的行匹配到第10行
awk -F: '/^root/,/^_lp/{print $1,$NF}' 1.txt # 用:分割,从 root开头的行到_lp开头的行,分割的字符的第一个和最后一个


awk 'BEGIN{FS=":";OFS="###"};/root/{print $1,$NF}' 1.txt # 以分号分割,输入内容以###拼接,  包含root的关键字,打印第1行和最后一行  root###/bin/sh
awk 'BEGIN{FS=":"};/root/{print $1"###"$NF}' 1.txt # 这句话和上面一样

awk 'BEGIN{FS=":"};{print "用户名:"$1",目录是"$NF}' 1.txt # 可以这样拼接

###################################################
date | awk '{print $1,$2,$4}' # 命令结果

4、使用进阶

1、printf 格式化输出

# %s 字符类型 %d 数值类型
# - 左对齐,默认右对齐
# 15 占15字符
# 默认不会再行尾自动换行,需要添加\n
awk -F: '{printf "%-15s %-15s \n",$1,$4}' 1.txt

2、变量定义

awk -F: -v NUM=3 '{print $NUM}' 1.txt # 变量名有$,此时是打印的第三个行
awk -F: -v NUM=3 '{print NUM}' 1.txt # 没有$ 此时打印的是变量
awk -v num=3 '{print num}' # 这样写,会等待输入文件名
awk -v num=3 'BEGIN {print num}' # 这样会打印变量

3、awk 中 BEGIN...END使用

  • BEGIN 程序开始前执行
  • END 所有文件处理完后执行
  • 用法 'BEGIN{awk语句};{处理中};END{awk语句}'
awk 'BEGIN{FS=":";print "第一行\t\t第二行\n*************"};{print $NF"\t\t"$(NF-1)};END{print "*************"}' 1.txt

4、和正则的综合运用

运算符 说明
==,!=,>,<,>=,<= 大于小于等于
~ 匹配
!~ 不匹配
!,&&,|| 逻辑非,与,或
awk -F: '/^root/,/^_lp/{print $0}' 1.txt # 以 root 开头 到 _lp开头 的行

awk -F: '/^root/;/^_lp/{print $0}' 1.txt # 以 root 开头 或者 _lp开头 的行
awk -F: '/^root/{print $0};/^_lp/{print $0}' 1.txt #和上面是等价的

awk 'NR>=1 && NR<=5 && $0 ~ /^root/{print $0}' 1.txt # 1到5行,并且以root开头的行

awk -F'[: ]' '{print $0}' 1.txt # 以冒号和空格为分割符

5、脚本编程

1、if结构

if [ xxx ];then
xxx
fi

awk 选项 '正则,地址定位{awk语句}' 文件名
awk 选项 '{if(表达式){语句1;语句2...}}'
awk 选项 '{if(表达式){语句1;语句2...} else {语句1;语句2...}}'
awk 选项 '{if(表达式){语句1;语句2...} else if(表达式){语句1;语句2...} else {语句1;语句2...}}'
awk -F: '{if($3=='4'){print $0}}' 1.txt # 第三个为4
awk -F: '{if($3>='60'){print $3" >60啊"} else {print $3"<60啊"}}' 1.txt

2、for循环

for ((int=1;i<=5;i++));do echo $i;done
awk 'BEGIN{for(i=1;i<=5;i++) {print i}}'
awk 'BEGIN{sum=0;for(i=1;i<=10;i+=2) sum=sum+i;{print sum}}' 

3、while 循环

awk 'BEGIN{i=1;while(i<=5){print i;i++}}'
awk 'BEGIN{i=1;while(i<=5){print i;i++}}' | awk '{sum+=$0};END{print sum}'
awk 'BEGIN{sum=0;i=1;while(i<=10){print i;sum=sum+i;i++}{print sum}}'

4、嵌套循环

awk 'BEGIN{for(y=1;y<=5;y++){for(x=1;x<=y;x++){printf x};print "-----"}}'

5、运用实例

awk -F: '{shells[$NF]++};END{for (i in shells) print i,shells[i]}' 1.txt

小技巧

# & 后台输出,> 输出到/dev/null,这样在脚本输出结果中就不会展示信息了
ping -c1 $ip &>/dev/null

# 取出目录
dirname ~/Desktop  
# 取出文件
basename ~/Desktop
###########################################
url=www.baidu.com
echo ${#url} # 获取url字符串的长度
echo ${url#*.} # 一个"#" 代表从左往右去掉一个/key/ ==> 结果是 baidu.com,去掉了 www.
echo ${url##*.} # 两个"#" 代表从左往右最大程度去掉/key/ ==> 结果是 com,去掉了 www.baidu.
echo ${url%.*} # 一个"%" 代表从右往左去掉一个/key/==> 结果是 www.baidu,去掉了右边的 .com
echo ${url%%.*} # 两个"#" 代表从右往左最大程度去掉/key/ ==> 结果是 www,去掉了 .baidu.com
################
 # 在我们使用cat <<EOF时,我们输入完成后,需要在一个新的一行输入EOF结束stdin的输入。
cat <<EOF
h  显示帮助命令
f  显示磁盘分区
q  退出程序
EOF
# 分界符(EOF)所在行的开头部分的制表符(Tab)都将被去除。可以解决由于脚本中的自然缩进产生的制表符。
cat <<-EOF
h  显示帮助命令
f  显示磁盘分区
q  退出程序
EOF
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342