mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-28 10:13:59 +00:00
sub/gsub capture-group iterate
This commit is contained in:
parent
f5d5d8be12
commit
f98d159959
4 changed files with 18 additions and 28 deletions
|
|
@ -463,31 +463,14 @@ int regmatch_or_die(const regex_t* pregex, const char* restrict match_string,
|
|||
// allocated. If not, input is returned. So in either case, the caller should
|
||||
// free the return value, and it is assumed that the input has been dynamically
|
||||
// allocated.
|
||||
char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement) {
|
||||
char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement, int *pall_captured) {
|
||||
const size_t nmatch = 10; // Capture-groups \1 through \9 supported, along with entire-string match
|
||||
regmatch_t matches[nmatch];
|
||||
*pall_captured = TRUE;
|
||||
|
||||
int matched = regmatch_or_die(pregex, input, nmatch, matches);
|
||||
if (!matched) {
|
||||
return input;
|
||||
} else if (matches[1].rm_so == -1) { // No capture groups: only a replacement string
|
||||
int so = matches[0].rm_so;
|
||||
int eo = matches[0].rm_eo;
|
||||
|
||||
int len1 = so;
|
||||
int olen2 = eo - so;
|
||||
int nlen2 = strlen(replacement);
|
||||
int len3 = strlen(&input[len1 + olen2]);
|
||||
int len4 = len1 + nlen2 + len3;
|
||||
|
||||
char* output = mlr_malloc_or_die(len4 + 1);
|
||||
strncpy(&output[0], input, len1);
|
||||
strncpy(&output[len1], replacement, nlen2);
|
||||
strncpy(&output[len1+nlen2], &input[len1+olen2], len3);
|
||||
output[len4] = 0;
|
||||
|
||||
free(input);
|
||||
return output;
|
||||
} else {
|
||||
// sed:
|
||||
// $ echo '<<abcdefg>>'|sed 's/ab\(.\)d\(..\)g/AYEBEE\1DEE\2GEE/'
|
||||
|
|
@ -504,6 +487,7 @@ char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* repla
|
|||
int idx = p[1] - '0';
|
||||
regmatch_t* pmatch = &matches[idx];
|
||||
if (pmatch->rm_so == -1) {
|
||||
*pall_captured = FALSE;
|
||||
sb_append_chars(psb, p, 0, 1);
|
||||
} else {
|
||||
sb_append_chars(psb, input, matches[idx].rm_so, matches[idx].rm_eo-1);
|
||||
|
|
@ -520,9 +504,10 @@ char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* repla
|
|||
}
|
||||
}
|
||||
|
||||
char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement) {
|
||||
const size_t nmatch = 1; // xxx temp: parameterize after adding capture-group support
|
||||
char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement, int* pall_captured) {
|
||||
const size_t nmatch = 10;
|
||||
regmatch_t pmatch[nmatch];
|
||||
*pall_captured = TRUE;
|
||||
|
||||
int match_start = 0;
|
||||
char* current_input = input;
|
||||
|
|
|
|||
|
|
@ -134,8 +134,9 @@ int regmatch_or_die(const regex_t* pregex, const char* restrict match_string,
|
|||
// If there is a match, input is freed and return value is dynamically
|
||||
// allocated. If not, input is returned. So in either case, the caller should
|
||||
// free the return value, and it is assumed that the input has been dynamically
|
||||
// allocated.
|
||||
char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement);
|
||||
char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement);
|
||||
// allocated. The by-reference all-captured flag is true on return if all \1,
|
||||
// etc. were satisfiable by parenthesized capture groups.
|
||||
char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement, int* pall_captured);
|
||||
char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement, int* pall_captured);
|
||||
|
||||
#endif // MLRUTIL_H
|
||||
|
|
|
|||
|
|
@ -203,8 +203,9 @@ mv_t sub_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3) {
|
|||
// * len4 = 6 = 2+3+1
|
||||
|
||||
mv_t sub_precomp_func(mv_t* pval1, regex_t* pregex, string_builder_t* psb, mv_t* pval3) {
|
||||
int all_captured = FALSE;
|
||||
char* input = pval1->u.strv;
|
||||
char* output = regex_sub(input, pregex, psb, pval3->u.strv);
|
||||
char* output = regex_sub(input, pregex, psb, pval3->u.strv, &all_captured);
|
||||
|
||||
free(pval3->u.strv);
|
||||
pval1->u.strv = NULL;
|
||||
|
|
@ -234,8 +235,9 @@ mv_t gsub_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3) {
|
|||
}
|
||||
|
||||
mv_t gsub_precomp_func(mv_t* pval1, regex_t* pregex, string_builder_t* psb, mv_t* pval3) {
|
||||
int all_captured = FALSE;
|
||||
char* input = pval1->u.strv;
|
||||
char* output = regex_gsub(input, pregex, psb, pval3->u.strv);
|
||||
char* output = regex_gsub(input, pregex, psb, pval3->u.strv, &all_captured);
|
||||
|
||||
free(pval3->u.strv);
|
||||
pval1->u.strv = NULL;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ release notes:
|
|||
* check minor incompatibilities
|
||||
* what else ...
|
||||
|
||||
! brew version?!?
|
||||
! brew version bump?!?
|
||||
|
||||
----------------------------------------------------------------
|
||||
MINOR: sampler UTs (w/ spec rand seed)
|
||||
|
|
@ -27,11 +27,13 @@ MAJOR: regex
|
|||
- sub($name, "a.*b(c.*d)e(f)g", "hij")
|
||||
- sub($name, "a.*b(c.*d)e(f)g", "h\1i\2j")
|
||||
|
||||
* mlr --regex-help; xrefs from put/filter/et al. -h's; into mld??
|
||||
|
||||
! finish gsub with capture groups
|
||||
! check so==-1 @ idx fetch
|
||||
! UTs x all x thorough
|
||||
! free-the-input flag. or, don't free inside regex_[g]sub
|
||||
! captured-all flag for gsub so caller can abend
|
||||
-> check perl/ruby/etc for prior expected behavior ...
|
||||
|
||||
* regex field names in rename: mlr rename '(.*)in(.*),\1foo\2'
|
||||
-> requires capture groups 1st
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue