工作中经常遇到的shell整理如下:
1.shell脚本传入时间参数并判断
#! /bin/bash
echo "[-DEBUG-] Start <$0>"
start_running_time=`date +%s`
if [ $# = 1 ]
then
start_dt=$1
end_dt=$1
elif [ $# = 2 ]
then
start_dt=$1
end_dt=$2
elif [ $# = 0 ]
then
start_dt=`date -d '-1 day' +%F`
end_dt=`date -d '-1 day' +%F`
fi
start_sec=`date -d $start_dt +%s`
end_sec=`date -d $end_dt +%s`
for ((i=$start_sec;i<=$end_sec;i+=86400))
do
partition_pt=`date -d @$i +%F`
partition_hour=`date -d @$i +%Y.%m.%d.%H`
start_hour_of_day=`date -d @$i +%Y.%m.%d.00`
end_hour_of_day=`date -d @$i +%Y.%m.%d.23`
yesterday_date=`date -d $partition_pt'-1 day' +%F`
done
2.查找文件并拷贝
find /export/home/pp_adm/sql -name "*.sql" | xargs -i cp {} ./
# linux
find . -name "load_olap*.sh.job" -type f | xargs -i cp {} /Users/xieyin/Downloads/My_test
# MacOS
find /Users/xieyin/Downloads/im_stats -name "load_olap*.sh.job" -type f | xargs -I F cp "F" /Users/xieyin/Downloads/My_test
3.删除包含指定字符串的行
sed -i '/dependencies=/d' load_olap*.sh.job
4.时间戳转换为时间格式
1598835492918 # 13位毫秒
date -d @1598835492.918 "+%Y-%m-%d %H:%M:%S" # 先转换成秒: 2020-08-31 08:58:12
date +%s # 秒: 1598843957
date -d @1598843957 "+%Y-%m-%d %H:%M:%S" # 转换成时间: 2020-08-31 11:19:17
5.获取时间戳(纳秒)
echo $[$(date +%s%N)]
6.获取时间戳(毫秒)
echo $[$(date +%s%N)/1000000]
7.转换为秒
start_sec=`expr 1598835492918/1000`
end_sec=`expr 1598844141960/1000`
duration_sec=`expr 1598844141960 - 1598835492918`
start_s=1598835492918
end_s=1598844141960
dura=$(($end_s-$start_s)) # 8649042
mins=$(($dura/1000/60))
8.grep精确匹配
line=olap_ch.warehouse_check
isFound=$(grep -i "\<$line\>" migration_01.lst)
b='abc(edg)ad(fi)rpqu'
echo $b|grep -o '(.*)'
9.获取文件大小
`ls -l filename | awk ‘{print $5}’`
10.只删除纯空行
sed '/^\s*$/d' file
11.删除纯空行和由空格组成的空行
sed '/^[ ]*$/d' file
12.hive 替换制表符、换行符
select regexp_replace('\t abc \n def \r hij', '\n|\t|\r', '');
13.判断上一个命令的执行结果
RC=$?
if [ $RC -eq 0 ];then
echo "Loading into clickhouse succeed!"
else
echo "Loading into clickhouse failed!"
exit 1
fi
14.替换
sed -i 's/zx_clickhouse/zx_temp/g' *.job
# 将 string 中第一个 match_string 替换成 replace_string
${string/#match_string/replace_string}
# 将 string 中的 match_string 全部替换成 replace_string
${string/%match_string/replace_string}
15.awk中引用shell变量
# 其实在awk里,是不能直接使用shell变量的
# 方法是:awk -v 选项让awk 里使用shell变量
TIME=60
awk -v time="$TIME" 'BEGIN{FS="|"} {if ($7>time) print $2 }'
# 这样要注意:在awk里,time不能加$符号。
16.判断文件大小是否为0
filename=/data/clickhouse/dump/dw_ch_zx_superset_activate_adid_d_incr_${partition_pt}
if [ ! -s $filename ];then
echo "$filename size is 0 then exit!"
exit 0
fi
17.Shell命令的输出信息同时显示在屏幕和保存到日志文件中
#直接覆盖日志文件
ls -l | tee ./t.log
#将输出内容附加到日志文件
ls -l | tee -a ./t.log
18.sed替换指定字符开头的行
var="version=6.1.1"
sed -i '/^version=/c'$var'' /etc/config.txt
sed -i '/^command=/echo skip' /etc/config.txt
var="command=echo skip"
sed -i '/^command=/c'$var'' load_ods_ch_*
sed -i '/^command=/c'$var'' load_dw_ch_*
# grep
sed '/^[\t]/p' a.txt
grep $'\t' a.txt
19.sed中使用变量
line=ods_ch.ods_zx_cm_sessionclose_d_incr
sed -i "/${line}/d" test.done
20.变量为空则赋默认值
param1=ck2
host=${param1:-ck1}
echo $host
21.去掉注释和空的行
sed '/^#.*\|^$/d' 1.tt说明:^#.*说明以#字符开头的行,^$表示手空行,中间的\|是转义,表示或。d表示删除。
22.后台运行shell命令
nohup xxx.sh > /dev/null 2>&1 &
23.找出文件中不包含指定字符
grep -v "2020-04-09" old_hdfs_size.rst > 01.rst
24.sed -e一次更改多替换文本中多个值
sed -e 's/11/22/' -e 's/55/99/' num.txt # 这个命令将num.txt中的11替换成22, 55替换成99.
25.sed删除包含指定字符串的所有行
sed -e '/2019-12-0[12]/d' temp.txt > not_exist_in_new_hdp_cluster.txt
26.在每个以for开头的前面插入字符串
sed '/^for/i\kinit -kt /home/im_stats/im_stats.keytab im_stats@MICHAT.COM\n\n' load_dw_ch_dim_zx_user_register_path.sh
find . -name "*.sh" | xargs grep -il "hive" | xargs sed -i '/^for/i\kinit -kt /home/im_stats/im_stats.keytab im_stats@MICHAT.COM\n\n'
find . -name "*.sh" | xargs grep -il "stats11.im.int" | xargs sed -i 's/stats1[1-2].im.int/sjpt-hds-michat-35.sin01/g'
sed 's/stats1[1-2].im.int/sjpt-hds-michat-35.sin01/g' load_dw_ch_zx_ympns_push_cnt_d_incr.sh
27.正则表达式 \w+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词:
echo this is a test line | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]
28.awk找出top hdfs文件大小
hadoop fs -ls awk 'BEGIN{sum=0}{sum+=$5}END{print sum/1024/1024/1024 GB}'
awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' test.log
hadoop fs -ls /server_log/*/*/*2019*06* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-06".txt
hadoop fs -ls /server_log/*/*/*2019*07* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-07".txt
hadoop fs -ls /server_log/*/*/*2019*08* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-08".txt
hadoop fs -ls /server_log/*/*/*2019*09* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-09".txt
hadoop fs -ls /server_log/*/*/*2019*10* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-10".txt
hadoop fs -ls /server_log/*/*/*2019*11* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-11".txt
hadoop fs -ls /server_log/*/*/*2019*12* | awk 'BEGIN{size=0}{size+=$5}END{printf("%10.3f GB\t%10.3f GB\t\n",size/1024/1024/1024,size*3/1024/1024/1024)}' > "2019-12".txt
im_stats@datanode03:/data/pub-four-mfs/stats/tools/ods_handler$ cat 2019*.txt
8144.689 GB 24434.067 GB
8483.775 GB 25451.324 GB
9414.310 GB 28242.930 GB
8868.708 GB 26606.125 GB
9782.030 GB 29346.090 GB
10533.918 GB 31601.755 GB
10857.728 GB 32573.185 GB
cat 2019*.txt | awk 'BEGIN{size=0;actsize=0}{size+=$1;actsize+=$3}END{printf("%10.3f GB\t%10.3f GB\n",size, actsize) }'
hadoop fs -ls /server_log/*/*/*2019-06* | less
-rw-r--r-- 3 im_stats supergroup 70409 2019-06-05 14:33 /server_log/admin-web/pro-a-bonus-task03/admin-web.log.2019-06-04.gz
29.awk把第一列第二列的值加起来
awk 'BEGIN{sum=0;act=0}{sum+=$1;act+=$2}END{print sum,act}' test.log
im_stats@datanode03:/data/pub-four-mfs/stats/tools/ods_handler$ cat test.log
12 24 aa.log
6 12 bb.log
3 6 cc.log
im_stats@datanode03:/data/pub-four-mfs/stats/tools/ods_handler$ awk 'BEGIN{sum=0;act=0}{sum+=$1;act+=$2}END{print sum,act}' test.log
21 42
30.获取某个月的第一个星期日
halo_stats@abp-ops-imdcnginx-1:~$ year=`date +%Y`
halo_stats@abp-ops-imdcnginx-1:~$ month=`date +%m`
halo_stats@abp-ops-imdcnginx-1:~$ day=`date +%d`
halo_stats@abp-ops-imdcnginx-1:~$ echo $year $month $day
2019 11 27
halo_stats@abp-ops-imdcnginx-1:~$ ncal $month $year
November 2019
Su 3 10 17 24
Mo 4 11 18 25
Tu 5 12 19 26
We 6 13 20 27
Th 7 14 21 28
Fr 1 8 15 22 29
Sa 2 9 16 23 30
# 以下2种都可以
ncal $month $year | grep -i "Su" | awk '{print $2}'
ncal $month $year | awk '{print $2}' | grep -v $year | head -1
31.大小写转换
1, 用tr
例如:UPPERCASE=$(echo $VARIABLE | tr '[a-z]' '[A-Z]') (把VARIABLE的小写转换成大写)
LOWERCASE=$(echo $VARIABLE | tr '[A-Z]' '[a-z]') (把VARIABLE的大写转换成小写)
2, 用typeset
typeset -u VARIABLE (把VARIABLE的小写转换成大写)
typeset -l VARIABLE (把VARIABLE的大写转换成小写)
例如:typeset -u VARIABLE
VARIABLE="True"
echo $VARIABLE
输出为TRUE
32.查看某天所有hive表的大小
hadoop fs -ls /user/hive/warehouse/dw_flume.db/*/pt=2019.08.11.* | grep -v "_SUCCESS" | awk -F' ' '{print $5,$8}' > 20190811_size.log
33.数组遍历
# 列表List
modes=(
"wifi_subset_users_base" # 一定要第一个运行
"adwords_first_new" # adwords纯新增用户
"adwords_old_first_new" # adwords历史所有纯新增用户
"googleplay_organic_first_new" # GP纯自然新增用户
"adwords_adjust_new" # adwords调整后新增用户
"adwords_old_adjust_new" # adwords历史所有调整后新增用户
"googleplay_organic_adjust_new" # GP调整后自然新增用户
"googleplay_old_organic" # 最后运行,有依赖前面的用户组
"googleplay_old_adjust_organic" # 最后运行,有依赖前面的用户组
)
for mode in "${modes[@]}";do
echo "foo"
done
34.判断字符串是否包含某个字符
str="this is a string"
[[ $str =~ "this" ]] && echo "$str contains this"
[[ $str =~ "that" ]] || echo "$str does NOT contain that"
结果为:
this is a string contains this
this is a string does NOT contains that
[[" 判断命令和 "=~"正则式匹配符号
35.全路径中获取脚本名
/root/xieyin/l1.sh
${line##*\/} # l1.sh
line=${line##*\/} # l1.sh
${line%%.*} #l1
var=http://www.aaa.com/123.htm.
1. # 号截取,删除左边字符,保留右边字符。
echo ${var#*//}
其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符
即删除 http://
结果是 :www.aaa.com/123.htm
2. ## 号截取,删除左边字符,保留右边字符。
echo ${var##*/}
##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符
即删除 http://www.aaa.com/
结果是 123.htm
3. %号截取,删除右边字符,保留左边字符
echo ${var%/*} # %/* 表示从右边开始,删除第一个 / 号及右边的字符
结果是:http://www.aaa.com
4. %% 号截取,删除右边字符,保留左边字符
echo ${var%%/*} # %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符
结果是:http:
5. 从左边第几个字符开始,及字符的个数
echo ${var:0:5} # 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。
结果是:http:
6. 从左边第几个字符开始,一直到结束
echo ${var:7} # 其中的 7 表示左边第8个字符开始,一直到结束。
结果是 :www.aaa.com/123.htm
36. awk截取")"右边的字符串
echo "sk2sl(kfei2p%fj4rsd)jasAdliels"|awk -F "\(|\)" '{print $2}'
37.在一些xml文件中,经常使用双引号,如果想要拿到双引号中的值,有两个小方法:
for example:
<config case="SetasWallpaper_4" loop="3" path="Reliability/Key_Usage_MTBF/Picture_Stress/case"/>
<config case="BrowserLaunchExit_1" loop="3" path="Reliability/Key_Usage_MTBF/Browser_Stress/case"/>
<config case="VideoThumbnail_6" loop="3" path="Reliability/Key_Usage_MTBF/Video_Stress/case" />
这两个命令可以将上面双引号中的内容全部拿出来。
awk -F'"' '{i = 1; while (i <= NF) {if ($i ~/=$/) print $(i+1);i++}}' plan.xml
sed 's/[^"]*="[″]∗["]∗"[^"]*/\1/g;s/"/\n/g' plan.xml
简单一点可以使用下面的命令:只拿其中的一个值。
awk:awk -F "[\"\"]" '{print $2}' aaa.txt
sed: cat aaa.txt | sed 's/.*".∗.∗".*/\1/'
echo "\`flag\` string," | awk -F "[\`\`]" '{print $2}'
echo 'case="VideoThumbnail_6" loop="3" path' | awk -F "[\"\"]" '{print $2}'
38.nohup后台运行
nohup hive_get_partitions.sh tables.lst tab_partitions.txt result.csv > nohup.out 2>&1 &
39.单引号中使用单引号
echo ''"'"'${hiveconf:runDt}'"'"''
40.例如查找2013-08-08到2013-09-01号之间的文件,使用如下命令即可:
find /log/ -name 'production.log-2013*' -newermt '2018-08-01' ! -newermt '2019-09-01'
2011/09/08 12:00 时间开始找一天內的,会列出 2011/09/07 12:00 ~ 2011/09/08 12:00 时间內的文件
找出 3 天”以前”被改动过的文件 (前第三天以前 → 2011/09/05 12:00 以前的文件) (> 72 小时)
find /log/ -name 'production.log-2013*' -newermt '2018-08-01' ! -newermt '2019-09-01
find默认查找当前目录和子目录,通过maxdepth限制只查当前目录:
find . -maxdepth 1 -type f -name "*.php"
找当前目录下指定时间日期并删除
find . -maxdepth 1 -type f -newermt '2018-08-01' ! -newermt '2019-09-10' | xargs rm
41.获取hive表分区的简单方法
table="ods_im.wifi_nearby_pull3_d_incr"
pt_cols=(`hive -e "desc $table" | sed -n '1,/^# col_name/!p' | awk '{print $1}'`)
${pt_cols[0]}=pt
${pt_cols[1]}=hour
${pt_cols[2]}=t_source
/app/hadoop/hive/bin/hive -e "desc $table_name" 2>/dev/null
uid string
longitude string
latitude string
sex string
gender string
listsize string
nextindex string
continueflag string
versioncode string
platform string
manufacturer string
osversion string
resultcode string
request_time string
clientip string
startindex string
fromtype string
is_useful string
app_id string
channelid string
clienttype string
devicename string
ssid string
bssid string
uids string
dim6 string
dim7 string
dim8 string
dim9 string
dim10 string
dim11 string
dim12 string
dim13 string
dim14 string
pt string
hour string
t_source string
# Partition Information
# col_name data_type comment
pt string
hour string
t_source string
42.将每行的最后一个,逗号改为分号)
# MAC
sed -E 's/\,([^\]*)$/\)\1/' $output
# Linux
# sed -r 's/\,([^\]*)$/ \1/' $output