工作中經(jīng)常遇到的shell整理如下:
1.shell腳本傳入時(shí)間參數(shù)并判斷
#! /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.時(shí)間戳轉(zhuǎn)換為時(shí)間格式
1598835492918 # 13位毫秒
date -d @1598835492.918 "+%Y-%m-%d %H:%M:%S" # 先轉(zhuǎn)換成秒: 2020-08-31 08:58:12
date +%s # 秒: 1598843957
date -d @1598843957 "+%Y-%m-%d %H:%M:%S" # 轉(zhuǎn)換成時(shí)間: 2020-08-31 11:19:17
5.獲取時(shí)間戳(納秒)
echo $[$(date +%s%N)]
6.獲取時(shí)間戳(毫秒)
echo $[$(date +%s%N)/1000000]
7.轉(zhuǎn)換為秒
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.判斷上一個(gè)命令的執(zhí)行結(jié)果
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 中第一個(gè) match_string 替換成 replace_string
${string/#match_string/replace_string}
# 將 string 中的 match_string 全部替換成 replace_string
${string/%match_string/replace_string}
15.awk中引用shell變量
# 其實(shí)在awk里,是不能直接使用shell變量的
# 方法是:awk -v 選項(xiàng)讓awk 里使用shell變量
TIME=60
awk -v time="$TIME" 'BEGIN{FS="|"} {if ($7>time) print $2 }'
# 這樣要注意:在awk里,time不能加$符號(hào)。
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命令的輸出信息同時(shí)顯示在屏幕和保存到日志文件中
#直接覆蓋日志文件
ls -l | tee ./t.log
#將輸出內(nèi)容附加到日志文件
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.變量為空則賦默認(rèn)值
param1=ck2
host=${param1:-ck1}
echo $host
21.去掉注釋和空的行
sed '/^#.*\|^$/d' 1.tt說明:^#.*說明以#字符開頭的行,^$表示手空行,中間的\|是轉(zhuǎn)義,表示或。d表示刪除。
22.后臺(tái)運(yùn)行shell命令
nohup xxx.sh > /dev/null 2>&1 &
23.找出文件中不包含指定字符
grep -v "2020-04-09" old_hdfs_size.rst > 01.rst
24.sed -e一次更改多替換文本中多個(gè)值
sed -e 's/11/22/' -e 's/55/99/' num.txt # 這個(gè)命令將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.在每個(gè)以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.正則表達(dá)式 \w+ 匹配每一個(gè)單詞,使用 [&] 替換它,& 對(duì)應(yīng)于之前所匹配到的單詞:
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.獲取某個(gè)月的第一個(gè)星期日
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.大小寫轉(zhuǎn)換
1, 用tr
例如:UPPERCASE=$(echo $VARIABLE | tr '[a-z]' '[A-Z]') (把VARIABLE的小寫轉(zhuǎn)換成大寫)
LOWERCASE=$(echo $VARIABLE | tr '[A-Z]' '[a-z]') (把VARIABLE的大寫轉(zhuǎn)換成小寫)
2, 用typeset
typeset -u VARIABLE (把VARIABLE的小寫轉(zhuǎn)換成大寫)
typeset -l VARIABLE (把VARIABLE的大寫轉(zhuǎn)換成小寫)
例如: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.數(shù)組遍歷
# 列表List
modes=(
"wifi_subset_users_base" # 一定要第一個(gè)運(yùn)行
"adwords_first_new" # adwords純新增用戶
"adwords_old_first_new" # adwords歷史所有純新增用戶
"googleplay_organic_first_new" # GP純自然新增用戶
"adwords_adjust_new" # adwords調(diào)整后新增用戶
"adwords_old_adjust_new" # adwords歷史所有調(diào)整后新增用戶
"googleplay_organic_adjust_new" # GP調(diào)整后自然新增用戶
"googleplay_old_organic" # 最后運(yùn)行,有依賴前面的用戶組
"googleplay_old_adjust_organic" # 最后運(yùn)行,有依賴前面的用戶組
)
for mode in "${modes[@]}";do
echo "foo"
done
34.判斷字符串是否包含某個(gè)字符
str="this is a string"
[[ $str =~ "this" ]] && echo "$str contains this"
[[ $str =~ "that" ]] || echo "$str does NOT contain that"
結(jié)果為:
this is a string contains this
this is a string does NOT contains that
[[" 判斷命令和 "=~"正則式匹配符號(hào)
35.全路徑中獲取腳本名
/root/xieyin/l1.sh
${line##*\/} # l1.sh
line=${line##*\/} # l1.sh
${line%%.*} #l1
var=http://www.aaa.com/123.htm.
1. # 號(hào)截取,刪除左邊字符,保留右邊字符。
echo ${var#*//}
其中 var 是變量名,# 號(hào)是運(yùn)算符,*// 表示從左邊開始刪除第一個(gè) // 號(hào)及左邊的所有字符
即刪除 http://
結(jié)果是 :www.aaa.com/123.htm
2. ## 號(hào)截取,刪除左邊字符,保留右邊字符。
echo ${var##*/}
##*/ 表示從左邊開始刪除最后(最右邊)一個(gè) / 號(hào)及左邊的所有字符
即刪除 http://www.aaa.com/
結(jié)果是 123.htm
3. %號(hào)截取,刪除右邊字符,保留左邊字符
echo ${var%/*} # %/* 表示從右邊開始,刪除第一個(gè) / 號(hào)及右邊的字符
結(jié)果是:http://www.aaa.com
4. %% 號(hào)截取,刪除右邊字符,保留左邊字符
echo ${var%%/*} # %%/* 表示從右邊開始,刪除最后(最左邊)一個(gè) / 號(hào)及右邊的字符
結(jié)果是:http:
5. 從左邊第幾個(gè)字符開始,及字符的個(gè)數(shù)
echo ${var:0:5} # 其中的 0 表示左邊第一個(gè)字符開始,5 表示字符的總個(gè)數(shù)。
結(jié)果是:http:
6. 從左邊第幾個(gè)字符開始,一直到結(jié)束
echo ${var:7} # 其中的 7 表示左邊第8個(gè)字符開始,一直到結(jié)束。
結(jié)果是 :www.aaa.com/123.htm
36. awk截取")"右邊的字符串
echo "sk2sl(kfei2p%fj4rsd)jasAdliels"|awk -F "\(|\)" '{print $2}'
37.在一些xml文件中,經(jīng)常使用雙引號(hào),如果想要拿到雙引號(hào)中的值,有兩個(gè)小方法:
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" />
這兩個(gè)命令可以將上面雙引號(hào)中的內(nèi)容全部拿出來。
awk -F'"' '{i = 1; while (i <= NF) {if ($i ~/=$/) print $(i+1);i++}}' plan.xml
sed 's/[^"]*="[″]?["]?"[^"]*/\1/g;s/"/\n/g' plan.xml
簡單一點(diǎn)可以使用下面的命令:只拿其中的一個(gè)值。
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后臺(tái)運(yùn)行
nohup hive_get_partitions.sh tables.lst tab_partitions.txt result.csv > nohup.out 2>&1 &
39.單引號(hào)中使用單引號(hào)
echo ''"'"'${hiveconf:runDt}'"'"''
40.例如查找2013-08-08到2013-09-01號(hào)之間的文件,使用如下命令即可:
find /log/ -name 'production.log-2013*' -newermt '2018-08-01' ! -newermt '2019-09-01'
2011/09/08 12:00 時(shí)間開始找一天內(nèi)的,會(huì)列出 2011/09/07 12:00 ~ 2011/09/08 12:00 時(shí)間內(nèi)的文件
找出 3 天”以前”被改動(dòng)過的文件 (前第三天以前 → 2011/09/05 12:00 以前的文件) (> 72 小時(shí))
find /log/ -name 'production.log-2013*' -newermt '2018-08-01' ! -newermt '2019-09-01
find默認(rèn)查找當(dāng)前目錄和子目錄,通過maxdepth限制只查當(dāng)前目錄:
find . -maxdepth 1 -type f -name "*.php"
找當(dāng)前目錄下指定時(shí)間日期并刪除
find . -maxdepth 1 -type f -newermt '2018-08-01' ! -newermt '2019-09-10' | xargs rm
41.獲取hive表分區(qū)的簡單方法
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.將每行的最后一個(gè),逗號(hào)改為分號(hào))
# MAC
sed -E 's/\,([^\]*)$/\)\1/' $output
# Linux
# sed -r 's/\,([^\]*)$/ \1/' $output