0

I have an issue with bash and its regex match ability that I for now think is a bug in bash but could also be me having missed something obvious. I hope it is the latter.

I have made this function in a bash script to spilt an address into fields. There is some debug output that will be removed eventually:

# name number, zip
function split_address
{
    local adr
    adr="$4"
    echo $adr
    local adr_regex
    adr_regex="[ ]*(.*[a-z ]) ([^,][^,]*),[ ]*([^ ]*)[ ]*"
    [[ $adr =~ $adr_regex ]]
    echo 1:X${BASH_REMATCH[1]}X
    echo 2:X${BASH_REMATCH[1]%% }X
    echo 3:Y${BASH_REMATCH[2]}Y
    echo 4:Y${BASH_REMATCH[2]%% }Y
    local x="${BASH_REMATCH[1]}"
    echo 5:X${x%% }X
    local x="${BASH_REMATCH[1]%% }"
    echo 6:X${x}X
    echo 7:X${x%% }X
    eval "$1='${BASH_REMATCH[1]%% }'"
    eval "$2='${BASH_REMATCH[2]%% }'"
    eval "$3='${BASH_REMATCH[3]}'"
}

I test it like this:

split_address roadname number zip "  Some string   42 dp ,  1234  "
echo X${roadname}X Y${number}Y Z${zip}Z

When called, I get this output:

Some string 42 dp , 1234
1:XSome string X
2:XSome string X
3:Y42 dp Y
4:Y42 dpY
5:XSome string X
6:XSome string X
7:XSome stringX
XSome string X Y42 dpY Z1234Z

First note that 4 has the space shown in 3 removed. This is what I want to happen in 2 when working on 1. Notice that 5 does not get the space removed even though this happens on the variable x. This was an attempt to work around this issue. Then I tried assigning the space-removing operation to the variable x but that also failed (shown in 6). But removing spaces on x in step 7 worked even though the line is identical to 5 and the input apparently as well.

Is this me doing something weird or is this a bug in bash?

For reference, I am working on Ubuntu 14 LTS with bash version 4.3.11(1)-release.

I see the same behavior with Cygwin-x64 with bash version 4.1.17(9-release.

I have verified that the character to be removed in deed is a space (using od on both source and test-call).

6
  • Call echo "$addr" and you'll see the difference. Let answer how many spaces after string and how many you can strip by ${...%% }
    – Costas
    Commented Dec 1, 2014 at 11:45
  • Why would you use bash as opposed to perl or text processing utilities for that? Commented Dec 1, 2014 at 11:46
  • Additionally you should remember that echo do substitute some trailing field separators (like a space e.g.) by one if you didn't put arguments into quotes.
    – Costas
    Commented Dec 1, 2014 at 11:52
  • Hmm I built the script under the assumption that %% would remove 1 or more copies of the substring listed. But it makes pathname expansion and that explains why my script fails. I find a different route.
    – galmok
    Commented Dec 1, 2014 at 12:20
  • As for me much easy to change regex string adr_regex="[ ]*(.*[a-z])[ ]*([0-9][^,]*),[ ]*([^ ]*)[ ]*" or better include some separator into input string (for example ;) and use it in regex.
    – Costas
    Commented Dec 1, 2014 at 22:19

2 Answers 2

2

%% does glob matching, not regex. That means ${foo%% } will remove the longest trailing string matching a single space character, which of course is just a single space character, and ${foo%% *} will remove the longest trailing string starting with a space character.

You'll probably be better off using awk to split the string into fields.

0

Following the solution giving by https://stackoverflow.com/questions/369758/how-to-trim-whitespace-from-bash-variable I fixed my script this way:

echo "8:X${BASH_REMATCH[1]%"${BASH_REMATCH[1]##*[![:space:]]}"}X"
eval "$1='${BASH_REMATCH[1]%"${BASH_REMATCH[1]##*[![:space:]]}"}'"

This is a double string manipulation and the first/inner part removes everything except the trailing spaces. This string is then used to cut off the same spaces at the end of the original string.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .