Shell脚本常用语法与命令


记录我工作中写脚本经常用到的命令和用法

1. 循环数组

arrs=("1" "2")
for arr in ${arrs[@]};do
  echo $arr
done
  • 通过下标取数组某个值 ${arrs[i]}
  • ${arrs[@]} 表示整个数组序列
  • 其中arrs[0] 也可以表示为arrs
  • 数组中元素也可以重新赋值, 比如执行完arrs=3之后数组就变成了(“3” “2”), 再执行arrs[1]=4, 数组就变成了(“3” “4”)

2. if else语句

name=nick
if [[ $name == "nick" ]];then
  echo "It's me."
elif [[ $name == "chun" ]];then
  echo "My wife."
else 
  echo "Others"
fi

3. 删除变量

之前遇到个情况, 我先定义了个变量arrs=("1" "2" "3"), 然后又执行arrs="a b c"。我以为字符串"a b c"会覆盖原来的数组, 但是事实并没有。只是把数组第一个元素值替换成了"a b c"。所以在使用之前用过的变量名之前,需要先删除变量, 执行unset arrs

4. 字符串操作

4.1 字符串截取

假设有变量var=https://blog.csdn.net/scl323

  • 4.2 通过#号截取

保留左数第一个分隔符右边的字符串
echo ${var#*:}结果是//blog.csdn.net/scl323

  • 这里分隔符是:, var是变量名,#是操作符,*:表示保留除分隔符右边的所有字符
  • 分隔符可以是多个字符,echo ${var#*net}的结果是/scl323
  • 4.3 通过##号截取

保留右数第一个分隔符右边的字符串
echo ${var##*/}结果是scl323

  • 4.4 通过%号截取

保留右数第一个分隔符左边的字符串
echo ${var%/*}结果是https://blog.csdn.net

  • 4.5 通过%%号截取

保留左数第一个分隔符左边的字符串
echo ${var%%/*}结果是https:

  • %#截然相反, 一个#是左数第一个分隔符,两个是右数第一个; 但是一个%是右数第一个分隔符, 两个是左数第一个。
  • 4.6 通过字符串下标截取

${变量名:开始字符位置:字符个数}

var=https://blog.csdn.net/scl323
# 从左边第几个字符开始, 4表示字符总个数
$ echo ${var:8:4}
blog

# 从左边第几个字符开始, 直到结束
$ echo ${var:8}
blog.csdn.net/scl323

# 从右边第几个字符开始,3表示字符总个数
$ echo ${var:0-6:3}
scl

# 从右边第几个字符开始, 直到结束
$ echo ${var:0-6}
scl323

4.2 字符串比较

操作符含义例子(值都为true)
==相等“a” == “a”
!=不等于“a” != “b”
=~包含“nicksong” =~ “nick”
>大于“2” > “1234”
<小于“1234” < “2”

注意:

  • 操作符左右都必须要有一个空格
  • 字符串排序是正常的Unicode字符排序规则

5. 远程执行命令

在搭集群的时候经常需要远程执行命令

5.1 前提条件

配置ssh免密登陆

5.2 命令格式

ssh [options] [user@]host [command]

  • 注意: 如果command里面如果有;则需要用双引号括起来

6. 循环遍历目录文件

对目录里面的文件进行循环遍历

#! /bin/bash

for file in `ls`; do
echo "文件名:"$file
done

7. 对文件逐行打印

对文件内容进行逐行打印

#! /bin/bash


cat /home/hdfs/data/t_s006_qh_bs_customer/cust_info.csv | while read line

do
  echo $line
  sleep 3
done

8. 修改文件格式(CR、CRLF)

在 vim 中用set ff?命令可以查看当前文件是什么格式的。

  • set ff=unix:修改文件格式为 unix,则换行为 CR
  • set ff=dos:修改文件格式为 dos,则换行为 CRLF

9. 用 AWK 命令计算文件某一列的总和

 awk -F' ' -v sum=0 '{sum += $3} END{print sum}'

10. wait 等待所有子进程结束

#! /bin/bash

# 这样能做到让 test1 和 test2 并行运行
bash test1.sh &
bash test2.sh &

wait
echo 'all is done'

11. shell 控制并发数执行

使用 FIFO 命名管道对并发数进行控制,原理是将管道当做一个线程池。

#!/bin/bash

# 需要并发执行的主代码放到这个 function 里面
function fun {
  echo $1
  # 模拟代码执行 5 秒
  sleep 5
}

################
# 创建命名管道  #
################

# 随便定义个文件名 $$ 表示当前进程号
fifo_file="/tmp/$$.fifo"
# 用 mkfifo 命令创建管道文件
mkfifo $fifo_file
# 并将文件描述符 6 和管道文件绑定。
exec 6<>$fifo_file
# 绑定完成就可以删除该管道文件了。
rm -f $fifo_file


#################
# 初始化池子大小 #
#################

# 线程数
thread_num=10
for i in $(seq 1 $thread_num); do
  # 往这个文件描述符里写 10 个 1
  # 从这里可以看到,前十个进程其实可以跟后十个进程通信
  echo 1 >&6
done

###########
# 执行主体 #
###########

# 待执行的数组
arr=$(seq 1 100)
# 遍历数组
for a in ${arr[@]}; do
  # 读取文件描述符里面一行,该操作类似于队列的 pop,读完就删除该行。
  # 如果文件描述符里面没有内容了,则会阻塞在这。所以读完 10 个之后
  # 就会在这里阻塞,直到前面的进程执行完并往描述符里增加一行。
  read -u6
  {
    # 执行主方法
    fun $a
    # 执行完之后往描述符中增加一行,相当于把自己拿到的 solt 再放回去。
    # 这一步想放啥进去就放啥进去,可以把当前的执行结果放进去,这样后面的
    # 线程就知道执行结果了。
    echo 1 >&6
  } &
  # 注意,执行主方法和释放锁应该放一起并放到后台执行。
done

# 等待所有进程执行完成
wait
# 关闭该文件描述符
exec 6>&-

持续更新, 欢迎关注

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值