問題描述:beeline -u 方式導出數據,結果文件中含有“|”(豎杠)。
執行的sql為:beeline -u jdbc:hive2://hadoop1:10000/default -e 'select * from tablename' > /home/tmp/result.nb
執行結果如下:
在Beeline中,結果可以被展示為多種格式,格式可以在outputformat參數中設置。下面是支持的輸出各式:
- table
- vertical
- xmlattr
- xmlelements
- separated-value formats (csv, tsv, csv2, tsv2, dsv)
其中table、vertical、xmlattr和xmlelements是按照特有的形式展示結果,比如vertical以key-value格式展示,xmlelements以xml格式展示。詳情見:
https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients
separated-value formats展示形式是將一行值按照不同分割符分開,主要包括五種分割輸出格式:csv, tsv, csv2, tsv2, dsv,目前csv和tsv已經被csv2和tsv2替代了。dsv,csv2和tsv2是從 Hive 0.14 開始引入的SV輸出格式,csv2使用的是逗號,tsv2使用的是tab空格,dsv是可配置的。對於dsv格式,分隔符可以通過用參數 delimiterForDSV 進行設置,默認是 '|'。
對於問題描述可知beeline輸出結果中字段之間使用“|”分割的,從前面分析可知, csv2和tsv2格式字段值分割符不可能是“|”,只有輸出為dsv格式,分割符可以設置,且默認分割符是“|”。可是在執行beeline時並未設置outputformat和delimiterForDSV 參數的值,說明使用的是Beeline默認的輸出格式,從outputformat說明中得知Beeline默認的輸出各式為table模式,所以接下來就需要弄清楚table模式下字段分隔符是否為“|”。
首先在BeeLine類中找到展示結果相關的代碼,如下圖所示:
從上圖可知,beeline使用的輸出格式是通過getOutputFormat()方法獲取的,那就進入該方法看看,如下圖所示:
可以看出getOutputFormat()方法直接將outputFormat值返回,接下來就需要看看outputFormat的值從哪來的,通過搜索得知除了outputFormat的默認值外,只有上圖中setOutputFormat(String outputFormat)會給outputFormat設置值,可是setOutputFormat(String outputFormat)只有在beeline執行語句中設置outputformat才會被調用,而事實並未在beeline中設置outputformat,所以getOutputFormat()獲取的是outputformat默認值,outputformat的默認值為"table",相關代碼如下:
TableOutputFormat類的print()方法實現邏輯如下:
從上圖可知,在print()方法中主要是設置表格中表頭、表體、表中值的展示格式,這里只關注表中字段值的分割符,因此繼續進入圖中第85行代碼看看對值的格式處理,代碼如下:
此處要看的是table默認下對值是怎么分割的,故header的值為false,所以會走該段代碼的else邏輯,顯然從圖中紅框中的代碼可知值之間使用“|”分割的。
經過以上分析可知,如果沒有在beeline執行語句中設置outputformat參數,默認展示格式會使用table模式,而table模式下字段值之間的分割符為“|”,因此我們看到beeline展示的結果是以“|”分割的。如果不想使用“|”作為分割符,可以通過以下方式來設置:
方式一:如果值之間用逗號分割,可以在beeline執行語句中加入--outputformat=csv2;如果值之間用tab分割,可以在beeline執行語句中加入--outputformat=tsv2。
(1)將beeline的輸出格式設置為csv2,即以逗號作為值之間的分割符。
SQL示例如下:
beeline -u jdbc:hive2://hadoop1:10000/default --outputformat=csv2 -e 'select * from tablename' > /home/tmp/result.nb
展示結果如下:
(2)將beeline的輸出格式設置為tsv2,即以tab作為值之間的分割符
SQL示例如下:
beeline -u jdbc:hive2://hadoop1:10000/default --outputformat=tsv2 -e 'select * from tablename' > /home/tmp/result.nb
展示結果如下:
方式二:如果方式的分割符不滿足需求,想通過其他分割符來分割beeline的執行結果值,可以在beeline執行語句中加入--outputformat=dsv2和--delimiterForDSV=DELIMITER。
(1)將beeline的輸出格式設置為dsv2,使用dsv2默認的分割符,即‘|’。
SQL示例如下:
beeline -u jdbc:hive2://hadoop1:10000/default --outputformat=dsv -e 'select * from tablename' > /home/tmp/result.nb
結果展示如下:
(2)將beeline的輸出格式設置為dsv2,並以tab作為值之間得分割符
SQL示例如下:
beeline -u jdbc:hive2://hadoop1:10000/default --outputformat=dsv --delimiterForDSV=$'\t' -e 'select * from tablename' > /home/tmp/result.nb
結果展示如下:
(3)將beeline的輸出格式設置為dsv2,並以#作為值之間得分割符
SQL示例如下:
beeline -u jdbc:hive2://hadoop1:10000/default --outputformat=dsv --delimiterForDSV=# -e 'select * from tablename' > /home/tmp/result.nb
結果展示如下:
備注:如果使用dsv2輸出格式,值之間的分割符使用默認值,在beeline執行語句中只需要加入--outputformat=dsv就可以;如果使用dsv2輸出格式,想通過自定義分割符來對值進行分割,不僅要在beeline執行語句中只需要加入--outputformat=dsv,還需要加入--delimiterForDSV=DELIMITER,實際使用時DELIMITER的值可替換為自定義的分割符。