1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2026-01-20 04:01:06 +00:00

expr: implement regular expressions

This commit is contained in:
Arcterus 2016-12-02 14:06:21 -08:00 committed by Alex Lyon
parent eb75085595
commit 9abc3208d3
10 changed files with 318 additions and 221 deletions

View file

@ -9,6 +9,7 @@ path = "expr.rs"
[dependencies]
libc = "*"
onig = "1.1"
uucore = { path="../uucore" }
[[bin]]

View file

@ -11,6 +11,7 @@
#[macro_use]
extern crate uucore;
extern crate onig;
mod tokens;
mod syntax_tree;
@ -95,9 +96,9 @@ separates increasing precedence groups. EXPRESSION may be:
ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2
ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2
STRING : REGEXP [NOT IMPLEMENTED] anchored pattern match of REGEXP in STRING
STRING : REGEXP anchored pattern match of REGEXP in STRING
match STRING REGEXP [NOT IMPLEMENTED] same as STRING : REGEXP
match STRING REGEXP same as STRING : REGEXP
substr STRING POS LENGTH substring of STRING, POS counted from 1
index STRING CHARS index in STRING where any CHARS is found, or 0
length STRING length of STRING

View file

@ -13,6 +13,7 @@
//!
use tokens::{Token};
use onig::{Regex, Syntax, REGEX_OPTION_NONE};
type TokenStack = Vec<(usize, Token)>;
pub type OperandsList = Vec< Box<ASTNode> >;
@ -105,6 +106,7 @@ impl ASTNode {
),
"|" => infix_operator_or(&operand_values),
"&" => infix_operator_and(&operand_values),
":" | "match" => operator_match(&operand_values),
"length" => prefix_operator_length( &operand_values ),
"index" => prefix_operator_index( &operand_values ),
"substr" => prefix_operator_substr( &operand_values ),
@ -350,6 +352,25 @@ fn infix_operator_and( values: &Vec<String> ) -> Result<String, String> {
}
}
fn operator_match(values: &Vec<String>) -> Result<String, String> {
assert!(values.len() == 2);
let re = match Regex::with_options(&values[1], REGEX_OPTION_NONE, Syntax::grep()) {
Ok(m) => m,
Err(err) => return Err(err.description().to_string())
};
if re.captures_len() > 0 {
Ok(match re.captures(&values[0]) {
Some(captures) => captures.at(1).unwrap().to_string(),
None => "".to_string()
})
} else {
Ok(match re.find(&values[0]) {
Some((start, end)) => (end - start).to_string(),
None => "0".to_string()
})
}
}
fn prefix_operator_length( values: &Vec<String> ) -> Result<String, String> {
assert!( values.len() == 1 );
Ok( values[0].len().to_string() )