Oracle的instr函数,已经在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';
在相应的hive的sql语句中,使用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>
*
* 注意: 如果String2在String1中没有找到,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);
}
}