Context
This is a follow-up question to a question I asked previously. A new detail/issue arose that I wasn't aware of prior to getting some amazing help from Kamil Maciorowski and Cyrus. I chose Kamil Maciorowski's answer due to his explanation and succinctness, though both answers achieved what I was looking for at the time. The precise reason for this script is explained in my previous question.
What it is
Kamil Maciorowski's code, called script.sh
:
#! /bin/bash
civic="$1"
street="$2"
if [ "$((civic%2))" = 1 ]; then
exclude=" even "
else
exclude=" odd "
fi
</path/to/addresses.txt grep -E "(^| )$street" \
| grep -v "$exclude" \
| awk -F '[ -]' -v civic="$civic" '
{if ($1 !~ /^[0123456789]*$/ || $2 !~ /^[0123456789]*$/) print
else if (civic>=$1 && civic<=$2) print}
'
This code allows me to pass in a house number and a street name. It will search addresses.txt
and return the proper string by checking address ranges, as well as addresses without any house number preceding the street name. Here's a sample of addresses.txt
demonstrating variation cases (anonymized):
1 fastest rd S: 99
2-58 fastest rd N: 98
42 fake st: ss12
1 test st: 1
2-199 test st: 2
200-300 even test st: 22
301-399 odd test st: 33
example dr N: ss5
example dr S: 226
956 sample rd N: 53
976-998 even sample rd N: 54
340-500 even sample rd S: ss11
401-487 odd sample rd S: 45
Using that data, I can run ./script.sh 1 fas
, and get the following output, which is perfect:
1 fastest rd s: 99
Another perfect example, ./script.sh 42 fak
:
42 fake st: ss12
Another good example, ./script.sh 20 ex
:
example dr N: ss5
example dr S: 226
Here it returns both example dr N
and S
, which is important for me to see, and is how I need it to behave.
What I'm having trouble with
In my original question I neglected to include strings in my addresses.txt
sample with just one house number, instead of a range (ex: 1 test st: 1
). To set up our data for this portion, here are some relevant strings from my above addresses.txt
sample:
1 fastest rd S: 99
2-58 fastest rd N: 98
1 test st: 1
2-199 test st: 2
956 sample rd N: 53
976-998 even sample rd N: 54
340-500 even sample rd S: ss11
401-487 odd sample rd S: 45
In the script's current state (What it is), running ./script.sh 89 tes
outputs:
1 test st: 1
2-199 test st: 2
Notice the 1 test st: 1
line. I'd like it to be able to return only 2-199 test st: 2
, as that matches my search of 89 tes
more precisely.
Another example, ./script.sh 483 sam
:
956 sample rd N: 53
401-487 odd sample rd S: 45
Notice it successfully recognizes 483 as odd, and matches it with 401-487 odd sample rd S: 45
range, instead of also including the 340-500 even sample rd S: ss11
range. However, it also returns 956 sample rd N: 53
, which does not match my search.
My attempts to solve the issue
Kamil Maciorowski hinted that the awk
portion of the script could be altered to "seek for the first not-entirely-numerical field and therefore know if there's a range, a single value or nothing before the street name." I tried adding another else if
line to awk
which would try to find a number, and print if the house # was alone, and followed by a space. I added else if (civic =~ /^[0123456789]\s$/) print}
:
</path/to/addresses.txt grep -E "(^| )$street" \
| grep -v "$exclude" \
| awk -F '[ -]' -v civic="$civic" '
{if ($1 !~ /^[0123456789]*$/ || $2 !~ /^[0123456789]*$/) print
else if (civic>=$1 && civic<=$2) print
else if (civic =~ /^[0123456789]\s$/) print}
'
Not entirely surprised I can't stop it from throwing syntax errors, as this kind of expression is new to me. I tried flipping the ($1 !~ /^[0123456789]*$/ || $2 !~ /^[0123456789]*$/)
and (civic>=$1 && civic<=$2)
lines, which returned only 340-500 even sample rd S: ss11
when searching for 480 sam
. However a search for 956 sam
did not produce 956 sample rd N: 53
.
I also tried to add another if exclusion at the start of script.sh
, but I realized single house numbers aren't constant like odd
or even
.
Any further help or suggestions would be greatly appreciated. I know I need to somehow exclude single house numbers when a range is successfully found, but I'm have real trouble wrapping my head around an approach to do so.
sed '/^[0-9]* /s/^\([0-9]*\)/\1-\1/' addresses.txt> newaddresses.txt
might be a good starting point.$1 !~ /-/ {$1 = $1 "-" $1}
, or$1 ~ /^[[:digit:]]+$/ {$1 = $1 "-" $1}
in your awk script.