數據分析工作中shell腳本的使用

這篇文章主要通過工作中shell腳本案例,介紹shell腳本中常用知識點

下面的這個腳本表示使用sqoop把生產數據庫mysql中的商戶交易數據導入到hive數據庫,且生產數據庫中商戶交易數據是分庫分表存放的(10個庫100個表中),分表分庫原則根據商戶F_merchant_id來分的,比如說一個商戶號F_merchant_id='xxxxx855',可以看到商戶號是倒數第三位是8,分庫的時候會存放到第8個數據庫中,最後兩位數字是55,所以分表的時候會存放到第55張表中。所以對於商戶號xxxxx855的所有交易數據會存放到第8個數據庫,第55個表中。

#抽取從2019年1月4號到2019年2月10日的所有商戶交易數據
begin_date="20190104" #定義開始時間變量
end_date="20190210"  #定義結束時間變量


while [ "$begin_date" -le "$end_date" ]    #$begin_date表示參數的引用
do
    y=${begin_date:0:4}
    m=${begin_date:4:2}
    d=${begin_date:6:2}

    echo "${y}-${m}"      
    begin_date=$(date -d "${begin_date}+1days" +%Y%m%d)
    
    y1=${begin_date:0:4}
    m1=${begin_date:4:2}
    d1=${begin_date:6:2}

  
for ((db=0;db<=9;db=db+1)) #從0到9,每次加1,共迭代10次  循環10個庫
do
   for ((j=0;j<=99;j=j+10))
  do
    querystr=''
    for((k=1;k<=10;k++))#一次union 10個表
        do
           tb1[$k]=$[(${j}+k-1)/10]  #相除
           tb2[$k]=$[(${j}+k-1)%10] #取餘
           table[$k]="select F_transaction_id,F_order_id,F_merchant_id from datafrog${db}.t_transaction_operation_by_merchant_${tb1[$k]}${tb2[$k]} where  F_time>='${y}-${m}-${d}' AND F_time<'${y1}-${m1}-${d1}'  "
        
            if [ $k -gt 1 ]
                        then
                                querystr="${querystr} union all ${table[$k]} "

                        else
                                querystr="${table[$k]}"
                   fi
           
    
        done
#下面的腳本大家不需要看,是爲整體效果做的展示
sqoop import \
--connect "jdbc:mysql://192.XXX.XX.XX/datafrog?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&tinyInt1isBit=false" \
--driver com.mysql.jdbc.Driver \
--username datafrog \
--password www.datafrog.com \
--query \
"${querystr}" \
--fields-terminated-by '\t' \
--fetch-size 50000 \
--direct \
--append \
--target-dir /user/hadoop/sqoop/notcm/tran/$y$m$d \
-m 1

done
done
done

1.創建一個shell腳本

linux 系統中打開文本編輯器(可以使用 vi/vim命令來創建文件),新建一個文件 test.sh,擴展名爲sh(sh代表shell)。輸入一些代碼,第一行一般是這樣:

如下:

#!/bin/bash
echo "Hello World !"

2.給shell腳本賦權限

一般寫好的shell腳本要先賦權限然才能後執行

chmod +x ./test.sh  #使腳本具有執行權限
./test.sh  #執行腳本

3.shell腳本中while循環使用

while 語句格式

while condition
do
    command
done

while循環案例

#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

運行腳本,輸出:

1
2
3
4
5

使用中使用了 Bash let 命令,它用於執行一個或多個表達式,變量計算中不需要加上$來表示變量

4.shell腳本中for 循環使用

for 循環與其他編程語言類似,Shell支持for循環。for循環一般格式爲:

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

例如,順序輸出當前列表中的數字:

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
輸出結果:

The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5

5.Shell腳本中字符串的拼接

如果想要在字符串變量後面拼接一個字符,可以用下面的方法:

value1=home

value2=${value1}"="   # 或者$value2=${value1}=

echo $value2

把要添加的字符串變量添加{}中,並且需要把$放到外面,上面的結果是:home=

還可以如下面的

[root@localhost sh]# var1=/etc/
[root@localhost sh]# var2=yum.repos.d/
[root@localhost sh]# var3=${var1}${var2}
[root@localhost sh]# echo $var3
/etc/yum.repos.d/

6.shell腳本中的關係運算符

  • -eq:等於 equal
  • -ne:不等於 not equal
  • -le:小於等於 less equal
  • -ge:大於等於 greater equal
  • -lt:小於 less than
  • -gt:大於 greater than

7.shell腳本中獲取系統時間的方法

  • 獲取今天時期:$(date +%Y%m%d)$(date +%F$(date +%y%m%d)

  • 獲取昨天時期:$(date -d yesterday +%Y%m%d)

  • 獲取前天日期:$(date -d -2day +%Y%m%d)

  • 獲取10天前的日期:$(date -d -10day +%Y%m%d)

  • n天前的 $(date -d "n days ago" +%y%m%d)

  • 明天:$(date -d tomorrow +%y%m%d)

  • 給定的日期減一天

$(date -d "20150416 -1 days" +%Y%m%d)

  • 給定的日期減去三天

$(date -d "20150416 -3 days" +%Y%m%d)

  • 給定的日期加上三天

date -d "20150416 3 days" "+%Y%m%d"

7.shell腳本中字符串截取

可以使用這樣的方法截取,表示從左邊第幾個字符開始以及字符的個數,用法爲:start:len
例如:

str='http://www.
你的域名.com/cut-string.html'

echo ${str:0:5}
輸出結果
結果是:http:

其中的 0 表示左邊第一個字符開始,5 表示字符的總個數。

8.shell腳本中數組的使用

數組中可以存放多個值。Bash Shell 只支持一維數組(不支持多維數組),初始化時不需要定義數組大小,與大部分編程語言類似,數組元素的下標由0開始。

(1)創建數組

shell數組用括號來表示,元素用"空格"符號分割開,語法格式如下:

array_name=(value1 ... valuen)

實列

#!/bin/bash

my_array=(A B "C" D)

我們也可以使用下標來定義數組:

array_name[0]=value0
array_name[1]=value1
array_name[2]=value2

(2)讀取數組

讀取數組元素值的一般格式是:

${array_name[index]}

實例

#!/bin/bash
my_array=(A B "C" D)

echo "第一個元素爲: ${my_array[0]}"
echo "第二個元素爲: ${my_array[1]}"
echo "第三個元素爲: ${my_array[2]}"
echo "第四個元素爲: ${my_array[3]}"
執行腳本,輸出結果如下所示:

$ chmod +x test.sh 
$ ./test.sh
第一個元素爲: A
第二個元素爲: B
第三個元素爲: C
第四個元素爲: D

9.shell腳本中重定向

針對於上面提到的sqoop抽取數據的腳本,工作中是使用azkaban做任務調度。但是有時候做其他的定時任務也使用crontab做來任務調度

比如下面的數據蛙課程案例,每天定時發送郵件的定時任務

35 8 * * * /root/anaconda3/bin/python3.6 /root/project/datafrog/datafrog_adventure.py >/tmp/load.log 2>&1 #郵件發送by 數據蛙

這個裏面就涉及到了shell腳本中的重定向,下面一起看看把

我們先來看下linux命令的執行過程

我們一起來看下,比如說一條linux命令

  • 一開始可能需要給這個命令一個輸入值,這個就叫標準輸入(Standard input),簡寫stdin
    ,其中可以通過鍵盤或者是文件的形式給命令一個輸入

  • 接着就開始執行命令,命令執行成功,就會把成功的結果輸出到屏幕上來,這個就叫標準輸出(standard output),簡寫stout

  • 若是命令行執行錯誤,就會把報錯的結果輸出到屏幕上來,這個就叫做標準錯誤(standard error),簡寫stderr

有時候我們在命令使用時,若不想命令的執行結果輸出的屏幕,需要輸入輸出到制定文件或者設備,就需要使用輸入、輸出重定向。

先看下輸出重定向的例子

#默認情況下,stdout和stderr默認輸出到屏幕
[root@st ~]# ls ks.cfg wrongfile
ls: cannot access wrongfile: No such file or directory
ks.cfg
#標準輸出重定向到stdout.txt文件中,錯誤輸出默認到屏幕。1>與>等價
[root@st ~]# ls ks.cfg wrongfile >stdout.txt
ls: cannot access wrongfile: No such file or directory
[root@st ~]# cat stdout.txt 
ks.cfg
#標準輸出重定向到stdout.txt,錯誤輸出到err.txt。也可以使用追加>>模式。
[root@st ~]# ls ks.cfg wrongfile >stdout.txt 2>err.txt
[root@st ~]# cat stdout.txt err.txt 
ks.cfg
ls: cannot access wrongfile: No such file or directory
#將錯誤輸出關閉,輸出到null。同樣也可以將stdout重定向到null或關閉
# &1代表標準輸出,&2代表標準錯誤,&-代表關閉與它綁定的描述符
[root@st ~]# ls ks.cfg wrongfile 2>&-
ks.cfg
[root@st ~]# ls ks.cfg wrongfile 2>/dev/null 
ks.cfg
#將錯誤輸出傳遞給stdout,然後stdout重定向給xx.txt,也可以重定向給null。順序爲stderr的內容先到xx.txt,stdout後到。
[root@st ~]# ls ks.cfg wrongfile >xx.txt 2>&1
#將stdout和stderr重定向到null
[root@st ~]# ls ks.cfg wrongfile &>/dev/null

注意關於2>&1的理解

  • 含義:將標準錯誤輸出重定向到標準輸出
  • 符號>&是一個整體,不可分開,分開後就不是上述含義了。比如有些人可能會這麼想:2是標準錯誤輸入,1是標準輸出,>是重定向符號,那麼"將標準錯誤輸出重定向到標準輸出"是不是就應該寫成"2>1"就行了?是這樣嗎?如果是嘗試過,你就知道2>1的寫法其實是將標準錯誤輸出重定向到名爲"1"的文件裏去了
  • 寫成2&>1也是不可以的

輸入重定向

#從stdin(鍵盤)獲取數據,然後輸出到catfile文件,按Ctrl+d結束
[root@st ~]# cat >catfile
this
is
catfile
[root@st ~]# cat catfile 
this
is
catfile
#輸入特定字符eof,自動結束stdin
[root@st ~]# cat >catfile <<eof
> this
> is
> catfile
> eof
[root@st ~]# cat catfile 
this
is
catfile

如果大家正在學習shell腳本使用的話,不防好好讀下sqoop抽取數據的腳本,通過實際的案例學習,成長速度會更快些

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章