Skip to content

Commit fbcda90

Browse files
committed
base implementation
1 parent 33644de commit fbcda90

File tree

4 files changed

+518
-2
lines changed

4 files changed

+518
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea/

README.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,33 @@
1-
# regex-range-builder
2-
Numeric range regular expression builder written in bash
1+
# Regex Range Builder
2+
Numeric range regular expression builder written in bash. Inspired by [erwinyusrizal's RegexNumericRangeGenerator](https://github.com/erwinyusrizal/RegexNumericRangeGenerator)
3+
I needed this for command line use, so I did a bash implementation. If this is useful for you too, you are welcome.
4+
5+
## Usage
6+
7+
```text
8+
range.sh [range] [params]
9+
10+
Examples:
11+
./range.sh 137 719
12+
./range.sh 137 719 1
13+
./range.sh 137 719 1 1
14+
./range.sh 137 719 0 1
15+
./range.sh 137 719 0 0 1
16+
17+
Range:
18+
Positive integers describing the search range.
19+
20+
Params
21+
Bool integers to set up a regular expression
22+
first - Matching Whole Lines
23+
second - Matching Leading Zeroes
24+
third - Matching Whole Word
25+
```
26+
27+
## Usage with grep
28+
29+
```text
30+
Examples:
31+
egrep "$(./range.sh 137 719 0 0 1)" README.md
32+
egrep "\\b$(./range.sh 719 2335)\\b" range_test.sh
33+
```

range.sh

Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
#!/usr/bin/env bash
2+
3+
function repeat() {
4+
local str="$1"
5+
local n="$2"
6+
if [ -z "${n}" ]; then
7+
echo "arg n is not set" >&2
8+
return 1
9+
fi
10+
11+
for (( x=0; x < $n; x++ )) do
12+
printf "${str}"
13+
done
14+
}
15+
16+
function parse_start() {
17+
local from=$1
18+
if [ -z "${from}" ]; then
19+
echo "arg from is not set" >&2
20+
return 1
21+
fi
22+
23+
local to=$2
24+
if [ -z "${to}" ]; then
25+
echo "arg to is not set" >&2;
26+
return 1
27+
fi
28+
29+
if (( "${from}" > "${to}")); then
30+
echo "arg from can not be greater than arg to" >&2
31+
return 1
32+
fi
33+
34+
if [ "${#from}" -eq "${#to}" ]; then
35+
local result=(${from} ${to})
36+
37+
echo "${result[@]}"; return
38+
fi
39+
40+
local break_point=$((10**${#from}))
41+
42+
local injection=$(parse_start "${break_point}" "${to}")
43+
44+
let break_point--
45+
46+
local result=(${from} ${break_point} ${injection})
47+
48+
echo "${result[@]}"
49+
}
50+
51+
function create_break_point() {
52+
local point=$1
53+
if [ -z "${point}" ]; then
54+
echo "arg point is not set" >&2
55+
return 1
56+
fi
57+
58+
declare -i r; let r="${point} + 1"; let r="${#r}"
59+
60+
local len="${#point}"
61+
if (( ${len} < ${r} )); then
62+
let len="$r - $len"
63+
for (( x=0; x < $len; x++ )) do
64+
printf "0"
65+
done
66+
fi
67+
68+
echo "${point}"
69+
};
70+
71+
function parse_end() {
72+
local from=$1
73+
if [ -z "${from}" ]; then
74+
echo "arg from is not set" >&2
75+
return 1
76+
fi
77+
78+
local to=$2
79+
if [ -z "${to}" ]; then
80+
echo "arg to is not set" >&2
81+
return 1
82+
fi
83+
84+
if (( "${from}" > "${to}")); then
85+
echo "arg from can not be greater than arg to" >&2
86+
return 1
87+
fi
88+
89+
declare -i len_from; let len_from="${#from}"
90+
declare -i len_to; let len_to="${#to}"
91+
92+
if [ ${len_from} -eq 1 ]; then
93+
local result=(${from} ${to})
94+
95+
echo ${result[@]}; return
96+
fi
97+
98+
local join_from=$(repeat "0" ${len_from})
99+
if [ "${join_from}" -eq "0${from:1}" ]; then
100+
local join_to=$(repeat "0" ${len_to})
101+
if [ "${join_to}" -eq "9${to:1}" ]; then
102+
local result=(${from} ${to})
103+
104+
echo ${result[@]}; return
105+
fi
106+
107+
if (( "${from:0:1}" < "${to:0:1}" )); then
108+
local join_to=$(repeat "0" ${len_to}-1)
109+
declare -i e; let e="${to:0:1}${join_to} - 1"
110+
111+
local break_point1=$(create_break_point $(($e + 1)))
112+
local injection=$(parse_end "${break_point1}" "${to}")
113+
if [ $? -eq 1 ]; then
114+
return 1
115+
fi
116+
117+
local break_point2=$(create_break_point ${e})
118+
local result=(${from} ${break_point2} ${injection})
119+
120+
echo ${result[@]}; return
121+
fi
122+
fi
123+
124+
local join_to=$(repeat "9" ${len_to})
125+
if [ "${join_to}" -eq "9${to:1}" ] && (( "${from:0:1}" < "${to:0:1}" )); then
126+
let i="${from:0:1} + 1"
127+
128+
local cut_to="${to:1}"
129+
local join_to=$(repeat "0" ${#cut_to})
130+
declare -i e; let e="$i${join_to} - 1"
131+
132+
local break_point1=$(create_break_point ${e})
133+
local injection=$(parse_end "${from}" "${break_point1}")
134+
if [ $? -eq 1 ]; then
135+
return 1
136+
fi
137+
138+
local break_point2=$(create_break_point $(($e + 1)))
139+
local result=(${injection} ${break_point2} ${to})
140+
141+
echo ${result[@]}; return
142+
fi
143+
144+
if (( "${from:0:1}" < "${to:0:1}" )); then
145+
let i="${from:0:1} + 1"
146+
147+
local cut_to="${to:1}"
148+
local join_to=$(repeat "0" ${#cut_to})
149+
declare -i e; let e="$i${join_to} - 1"
150+
151+
local break_point1=$(create_break_point $e)
152+
local injection1=$(parse_end "${from}" "${break_point1}")
153+
if [ $? -eq 1 ]; then
154+
return 1
155+
fi
156+
157+
local break_point2=$(create_break_point $(($e + 1)))
158+
local injection2=$(parse_end "${break_point2}" "${to}")
159+
if [ $? -eq 1 ]; then
160+
return 1
161+
fi
162+
local result=(${injection1} ${injection2})
163+
164+
echo ${result[@]}; return
165+
fi
166+
167+
local o=$(parse_end "${from:1}" "${to:1}")
168+
if [ $? -eq 1 ]; then
169+
return 1
170+
fi
171+
172+
local first_from="${from:0:1}"
173+
result=()
174+
IFS=$' ';
175+
for item in ${o}
176+
do
177+
result+=("$first_from$item")
178+
done
179+
180+
echo "${result[@]}"
181+
};
182+
183+
function parse_into_regex() {
184+
local range=$1
185+
if [ -z "${range}" ]; then
186+
echo "arg range is not set"
187+
return 1
188+
fi
189+
190+
local result=()
191+
192+
local i=0
193+
local prev
194+
IFS=$' ';
195+
for item in ${range}
196+
do
197+
let i++
198+
if [ $i -eq 1 ]; then
199+
prev=${item};
200+
continue
201+
fi
202+
let i=0
203+
204+
local s=""
205+
local repeat=0
206+
local reg=""
207+
208+
len=${#prev}
209+
for ((a=0; a<len; a++)); do
210+
local from=${prev:$a:1};
211+
local to=${item:$a:1};
212+
213+
if [ "${from}" -eq "${to}" ]; then
214+
reg+="${from}"
215+
else
216+
declare -i from_p; let from_p="${from} + 1"
217+
if [ ${from_p} -eq "${to}" ]; then
218+
reg+="[${from}${to}]"
219+
else
220+
local from_to="${from}${to}"
221+
if [ "${s}" = "${from_to}" ]; then
222+
let repeat++
223+
fi
224+
225+
s="${from_to}";
226+
declare -i prev_m; let prev_m="${#prev} - 1"
227+
228+
if [ $a -eq ${prev_m} ]; then
229+
if [ "${repeat}" -gt 0 ]; then
230+
local repeat_p=$(( "${repeat} + 1" ))
231+
reg+="{${repeat_p}}"
232+
else
233+
reg+="[${from}-${to}]"
234+
fi
235+
else
236+
if [ "${repeat}" -eq 0 ]; then
237+
reg+="[${from}-${to}]"
238+
fi
239+
fi
240+
fi
241+
fi
242+
done
243+
244+
result+=(${reg})
245+
done
246+
247+
echo "${result[@]}"
248+
};
249+
250+
function parse_into_pattern() {
251+
local reg=$1
252+
if [ -z "${reg}" ]; then
253+
echo "arg reg is not set"
254+
return 1
255+
fi
256+
257+
local line=$2
258+
if [ -z "${line}" ]; then
259+
line=0
260+
fi
261+
262+
local zeroes=$3
263+
if [ -z "${zeroes}" ]; then
264+
zeroes=0
265+
fi
266+
267+
local word=$4
268+
if [ -z "${word}" ]; then
269+
word=0
270+
fi
271+
272+
reg=${reg// /|}
273+
if [ "${line}" -eq 1 ] && [ "${zeroes}" -eq 1 ]; then
274+
echo "^0*(${reg})$"
275+
else
276+
if [ "${zeroes}" -eq 1 ]; then
277+
echo "0*(${reg})"
278+
else
279+
if [ "${line}" -eq 1 ]; then
280+
echo "^(${reg})$"
281+
else
282+
if [ "${word}" -eq 1 ]; then
283+
echo "\\b(${reg})\\b"
284+
else
285+
echo "(${reg})"
286+
fi
287+
fi
288+
fi
289+
fi
290+
};
291+
292+
function combine() {
293+
local from=$1
294+
local to=$2
295+
local re='^[0-9]+$'
296+
297+
if [ -z "${from}" ]; then
298+
echo "arg from is not set" >&2
299+
return 1
300+
fi
301+
302+
if ! [[ $from =~ $re ]] ; then
303+
echo "arg from is not a number" >&2;
304+
return 1
305+
fi
306+
307+
if [ -z "${to}" ]; then
308+
echo "arg to is not set" >&2
309+
return 1
310+
fi
311+
312+
if ! [[ $to =~ $re ]] ; then
313+
echo "arg to is not a number" >&2;
314+
return 1
315+
fi
316+
317+
if (( "${from}" > "${to}")); then
318+
echo "arg from can not be greater than arg to" >&2
319+
return 1
320+
fi
321+
322+
local start_range=$(parse_start "${from}" "${to}")
323+
local end_range=""
324+
325+
local i=0
326+
local prev
327+
IFS=$' ';
328+
for item in ${start_range}
329+
do
330+
let i++
331+
if [ $i -eq 1 ]; then
332+
prev=${item}
333+
continue
334+
fi
335+
let i=0
336+
337+
local middle_range=$(parse_end "${prev}" "${item}")
338+
if [ "${#end_range}" -ne 0 ]; then
339+
end_range="$end_range "
340+
fi
341+
end_range+="${middle_range}"
342+
done
343+
344+
local range=$(parse_into_regex "${end_range}")
345+
parse_into_pattern "${range}" $3 $4 $5
346+
}
347+
348+
if [ ! -z $1 ] && [ ! -z $2 ]; then
349+
combine $1 $2 $3 $4 $5
350+
fi

0 commit comments

Comments
 (0)