oracle的instr函式在hive上面的實現

月夜原野發表於2017-10-16

Oracleinstr函式,已經在hive上面做了相應的實現,使用方法如下:

在使用該方法的hsql指令碼中或者hive客戶端中,加入如下命令:

add jar /opt/hive/hive-0.10.0-cdh4.5.0/lib/function.jar;

create temporary function instr as 'net.fone.www.function.udf.Instr';

 

在相應的hivesql語句中,使用instr即可,如下:

select id, substr(cv,

              instr(cv, '.', 1, 4) + 1,

              instr(cv, '.', 1, 5) - instr(cv, '.', 1, 4) - 1) v_fcid,

       substr(cv, instr(cv, '.', 1, 5) + 1) v_scid,

       cv

  from tv_player_log t

 

函式說明:

/**

* Oracle/PLSQL中,instr函式返回要擷取的字串在源字串中的位置。</br></br>

*

 * 語法如下:instr( string1, string2 [, start_position [, nth_appearance ] ]

* )

*

 * string1 源字串,要在此字串中查詢。 string2 要在string1中查詢的字串. start_position

* 代表string1</br></br> 的哪個位置開始查詢。此引數可選,如果省略預設為1.

* 字串索引從1開始。如果此引數為正,從左到右開始檢索,如果此引數為負,從右到左檢索,返回要查詢的字串在源字串中的開始索引。</br></br>

*注:當子串為字串,且start_position是負數的時候,實際的匹配界限為0-(string1.lenth+start_position+string2.length)

 * nth_appearance 代表要查詢第幾次出現的string2. 此引數可選,如果省略,預設為 1.如果為負數系統會報錯。</br></br>

*

 * 注意: 如果String2String1中沒有找到,instr函式返回0.</br>

*

 */

 

引數string2如果是特殊字元,需要新增特殊處理,已經對”.”,”*”等符號進行了轉義處理。

實現如下:

package net.fone.www.function.udf;


import java.util.ArrayList;

import java.util.List;

import java.util.regex.MatchResult;

import java.util.regex.Matcher;

import java.util.regex.Pattern;


import org.apache.commons.lang.StringUtils;

import org.apache.hadoop.hive.ql.exec.UDF;


/**

 * 

 * 在Oracle/PLSQL中,instr函式返回要擷取的字串在源字串中的位置。</br></br>

 * 語法如下:instr( string1, string2 [, start_position [, nth_appearance ] ])

 * string1 源字串,要在此字串中查詢。 string2 要在string1中查詢的字串. start_position

 * 代表string1</br></br> 的哪個位置開始查詢。此引數可選,如果省略預設為1.

 * 字串索引從1開始。如果此引數為正,從左到右開始檢索,如果此引數為負,從右到左檢索,返回要查詢的字串在源字串中的開始索引。</br></br>

 * 注:當子串為字串,且start_position是負數的時候,實際的匹配界限為0-(string1.lenth+start_position+string2.length)

 * 

 * nth_appearance 代表要查詢第幾次出現的string2. 此引數可選,如果省略,預設為 1.如果為負數系統會報錯。</br></br>

 * 注意: 如果String2在String1中沒有找到,instr函式返回0.</br>

 * 

 * @author caoyong

 */


public class Instr extends UDF {

// private Text line = new Text("");


public Instr() {


}


public int evaluate(String... args) {

Pattern pattern = null;

Matcher matcher = null;

String source = null;

String subStr = null;


int startIndex = 0;


int regionStartIndex = 0;

int regionEndIndex = 0;

int seqIndex = 1;


int sourceLength = 0;

int subLength = 0;

if (args == null || args.length < 2) {

return 0;

}


source = args[0].toString();

subStr = args[1].toString();

if (subStr.equals(".") || subStr.equals("*")) {

subStr = "\\" + subStr;

}

sourceLength = source.length();

subLength = subStr.length();


if (StringUtils.isBlank(source) || StringUtils.isBlank(subStr)) {

return 0;

}


pattern = Pattern.compile(subStr);

matcher = pattern.matcher(source);


List<Integer> indexList = new ArrayList<Integer>();


if (args.length >= 3) {// 如果第三個引數不為空,則

startIndex = Integer.valueOf(args[2].toString());

if (startIndex == 0) {

return 0;

}

if (startIndex < 0) {

if (sourceLength + startIndex + subLength < 0) {

return 0;

}

regionEndIndex = sourceLength + startIndex + subLength;

regionEndIndex = (regionEndIndex > sourceLength) ? sourceLength : regionEndIndex;

regionStartIndex = 0;

} else {

regionEndIndex = sourceLength;

regionStartIndex = startIndex - 1;

}

} else {

regionEndIndex = sourceLength;

regionStartIndex = startIndex;

}

matcher.region(regionStartIndex, regionEndIndex);

while (matcher.find()) {

MatchResult result = matcher.toMatchResult();

indexList.add(result.start() + 1);

}


if (args.length >= 4) {

seqIndex = Integer.valueOf(args[3]);

}


if (seqIndex > indexList.size()) {

return 0;

} else if (startIndex >= 0) {

return indexList.get(seqIndex - 1);

} else {

return indexList.get(indexList.size() - seqIndex);

}


// return 0;


}


public static void main(String[] args) {


Instr instr = new Instr();

// for (int k = -1; k > -32; k--) {

// int i = instr.evaluate("abcabcjjjjabcabcjjjabcabc", "abc", "" + k,

// "2");

// System.out.println(k + "," + i);

// }


int i = instr.evaluate("31.3.24.3245.3001.3001020", ".", "" + 1, "4");

System.out.println(i);

}

}



相關文章