shell script 相关

一、shell script 编程模板


#!/bin/bash

 #通常用作注释,但是#!放在一起是一个特殊的表示符,标志着这是一个shell script,其后的路径指出了用来解释这个script的程序位置。

bash只是shell的一种,还有很多其它shell,如:sh,csh,ksh,tcsh,...

#!/bin/bash只能放在第一行,不在第一行的#!/bin/bash,只是一个注释。

#!/bin/sh 表示用 Bourne shell 来执行.
如果系统中没有 sh, 会选择兼容的 shell 解释器

#!/bin/bash 表示用 Bash shell 来执行
如果系统中没有 bash, 会选择兼容的 shell 解释器


变量赋值

# $0 代表被调用者自身的名字
# $1 代表第一个参数,$N 代表第 N 个参数
# $# 代表参数个数
# $@ 代表所有参数,类型是个数组,想传递所有参数给其他命令用 cmd "$@" 
# $* 空格链接起来的所有参数,类型是字符串
arg1=$1 # 获取命令行输入参数,或单引号
file_path="/tmp/test.txt" # 常量赋值
count=$(ls /tmp | wc -l) # 获取命令执行结果
count=`ls /tmp | wc -l` # 获取命令执行结果

size=`wc -c /tmp/a.txt | awk '{print $1}'`
size=`echo "scale=3; $size/$((1024**3))" | bc`
echo $size'GB'

current_script_path=$(readlink -f "$0") # 获取当前脚本路径
current_script_dir=$(dirname $(readlink -f "$0")) # 获取当前脚本所在目录

root=$(pwd)

path=/home/a.txt
a=$(basename $path) # a.txt
a=`basename $path`
a=$(basename $path .txt).json # a.json

四则运算 expr,let,bc,(())

# expr命令是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串,不支持浮点除法
a=`expr 1 + 2`
a=$(expr 1 - 2)
a=$(expr 2 \* 3) # 使用乘号时,必须用反斜线屏蔽其特定含义
a=$(expr 4 / 2)

# let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
let a=1+2
let a=1-2
let a=2*3
let a=4/2
let a=(1+2)*3

# bc 命令是任意精度计算器语言,通常在linux下当计算器用
a=`echo "1+2" | bc`
a=`echo "1-2" | bc`
a=`echo "2*3" | bc`
a=`echo "4/2" | bc`
a=`echo "(1+2)*3" | bc`
a=`echo "10^2" | bc`
a=`echo "scale=2; 0.5/2" | bc` # 浮点除法

# (()) 的用法
a=$((1+2))
a=$((1-2))
a=$((2*3))
a=$((4/2))
a=$(((1+2)*3))

#自增加1
((a++))
let a++ #let a+=1
a=`expr $a + 1`
a=$[$a+1]
a=$(($a+1))

判断

#!/bin/bash

#判断后缀
file=$1
extension="${file##*.}"
if [ ! "$1" ] || [ "$extension" != "txt" ]; then
  echo "eg. bash ./test.sh a.txt"
  exit 1
elif [ ${file:0:1} = "A" ]; then
  echo "begin with 'A', skip"
else
  echo "pass"
fi

#判断目录是否存在
dir=$1
if [ ! -d "$dir" ]; then
  mkdir $dir
  root="."
fi

#判断文件是否存在
file=$1
if [ -f "$file" ]; then
  rm $file
fi

循环

1、逐行读取文件的3种方法:

方法1:while循环中执行效率最高,最常用的方法。

while read line
do
  if [ ${line:0:1} = "#" ]; then
    continue
  fi
  
  echo $line
done  < $1

方法2:管道法

cat filename | while read line
do
    echo $line
done

方法3:for 循环

for  line  in  `cat filename`
do
    echo ${line}
done

 2、定时处理

#!/bin/bash

a=0
while true; do # while [ 1 ]
  ((a++))
  echo -ne "$a\r" #不换行刷新数据
  sleep 3s
done

sleep 1 睡眠1秒
sleep 1s 睡眠1秒
sleep 1m 睡眠1分
sleep 1h 睡眠1小时 


输出

a='alan'
b=1314
d='1'
echo ${a}${b}"c"$(expr $d - 1)
echo "${a}${b}c$(expr $d - 1)"
echo -ne "$a\r"  #不换行刷新数据

参数:

-n 不输出最后的\n,不自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:
    \r 光标移至行首,但不换行
    \t 插入tab
    \n 换行且光标移至行首
    \\ 插入\字符
    \v或\f 换行但光标仍旧停留在原来的位置;
printf [format] [文本1] [文本2] ..

printf "%s %s %s\n" 1 2 3 4
printf " (%.2f) " 1 2 3 4
printf "%X" 10 #10进制转16进制
printf "%d" 0xA #16进制转10进制
printf "%-10s %-10s %-4s \n" 姓名 性别 年龄 小明 男 20 小花 女 18 #"-"表示左对齐, "10 10 4" 表示占的字符位数, 不够不空格

常用格式替换符

%s

字符串

%f

浮点格式

%d,%i

十进制整数

%o

八进制值

%x

十六进制值(a-f)

%X

十六进制值(A-F)

%%

表示%本身

常用转义字符

\n

换行

\t

水平制表符

\\

表示\本身


文件描述符&输出重定向

在Linux系统中0 1 2是一个文件描述符
0表示标准输入(stdin)
1表示标准输出(stdout)
2表示标准错误输出(stderr)
> 默认为标准输出重定向,与 1> 相同
2> 标准错误输出重定向
2>&1 意思是把标准错误输出重定向到标准输出
&>file 意思是把标准输出和标准错误输出都重定向到文件file中

/dev/null是一个文件,这个文件比较特殊,所有传给它的东西它都丢弃掉,就像一个无底洞。

ls /tmp > /dev/null 2>&1 # 默认情况是1,也就是等同于1> /dev/null 2>&1。意思就是把标准输出重定向到“黑洞”,还把错误输出2重定向到标准输出1,也就是标准输出和错误输出都进了”黑洞“

ls /tmp 2>&1 >/dev/null # 意思就是把错误输出2重定向到标准输出1,也就是屏幕,标准输出进了“黑洞”,也就是标准输出进了黑洞,错误输出打印到屏幕

分割字符

OLD_IFS="$IFS"
IFS="," # 按逗号分割string,默认按空格分割
array=($string)
IFS="$OLD_IFS"

echo ${array[-1]} # 数组的最后一个数
for var in ${array[@]} # @表示取数组的所有数值
do
   echo $var
done

字符串截取(分离文件名和后缀)

#!/bin/bash

FILE="example.tar.gz"
echo "${FILE%%.*}" # example --> (%%号是运算符,.* 表示从右边开始删除最后一个.号及右边的所有字符)
echo "${FILE%.*}" # example.tar --> (%号是运算符,.* 表示从右边开始删除第一个.号及右边的所有字符)
echo "${FILE#*.}" # tar.gz --> (#号是运算符,*. 表示从左边开始删除第一个.号及左边的所有字符)
echo "${FILE##*.}" # gz --> (##号是运算符,*. 表示从左边开始删除最后一个.号及左边的所有字符)
filename="${FILE%.*}"
extension="${FILE##*.}"

echo ${FILE:0:5} # examp --> 从左边第几个字符开始,及字符的个数
echo ${FILE:2} # ample.tar.gz --> 从左边第几个字符开始,一直到结束
echo ${FILE:0-6:3} # tar --> 从右边第几个字符开始,及字符的个数
echo ${FILE:0-1} # z --> 从右边第几个字符开始,一直到结束
# 注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

二、常用shell命令

ls | wc -l # 计算当前目录下的文件数
ls /tmp | grep "*.txt" |  wc -l # 计算/tmp下txt文件的个数
cat a.txt | wc -l # 计算文件的行数
df -h # 查看磁盘使用情况
du -sh * # 查看当前目录下文件大小

将文件夹下的文件名存到文本中(提取 image 文件夹下所有图像序列的名字,按顺序保存为时间戳)

find image_dir -name "*.jpg" -printf "%f\n" > image_dir/timestamps.txt
sed -i -e 's/.jpg//g' image_dir/timestamps.txt
sort image_dir/timestamps.txt -o image_dir/timestamps.txt // 默认升序

找到后台程序进程号、杀掉进程、重启

ps -aux | grep <exe_name>
kill -9 <process_id>
nohup <exe_name> > out.log &
tail -f out.log

ps aux | grep <exe_name> | grep -v grep | awk '{print $2}' | sudo xargs kill -9

文本处理:

仅保存指定列满足条件的行

保留指定列

按指定列排序

awk '{print $2}' | awk -F: '{print $NF}'

awk -F " " '{print val$4}' val="$a"

sudo du -h --max-depth 1 查看当前文件夹下一级目录的大小
awk -F '_' '$4>3&&$4<4{print}' a.txt >> b.txt # 取a.txt中以"_"分隔满足条件的列,追加在b.txt中
sort -t_ -k1.2,1.2 -k4,4 a.txt -o b.txt # 对a.txt中以"_"作为分隔符,按第1列第2个字符排序,若相同,再按第四列排序,保存在b.txt中
cat a.txt | cut -d '_' -f 1 > b.txt # 取a.txt中以"_"分隔的第1列,保存在b.txt中
sort -u -r # 降序、不重复
find image_dir -name "*.jpg" -printf "%f\n" > image_dir/timestamps.txt
sed -i -e 's/.jpg//g' image_dir/timestamps.txt 
sed -i '/xxx/d' filename # 删除包含"xxx"的行,原地操作
ls -lh
sed -n 指定行数;-n '2p':第二行;-n '1,3p':第一至三行

mkdir -p ${root}/{dir1,dir2}
set -e #在"set -e"之后出现的代码,一旦出现了返回值非零,整个脚本就会立即退出,那么就可以避免一些脚本的危险操作。

遍历文件夹下所有jar包文件,拷贝到目标目录中
find . -name "*.jar" | xargs -i cp {}  /dir
cp后面的{}会被替换成xargs的输入

查找文件夹(包括子文件夹)下包含关键字的行及其所在的文件:

grep foo * -R
<other output> | grep "foo*"

猜你喜欢

转载自blog.csdn.net/A_L_A_N/article/details/98853011
今日推荐