I'd like to extract the port number from an address string. The whole string looks like this:
connect single-cluster --listen-addr=127.0.0.1:12345 --filename=hello
or
connect single-cluster --listen-addr=127.0.0.1 --filename=hello
I'd like to save the address and port from the listen-addr to two variables: ADDR and PORT. If the port does not exist in the input string, just leave the PORT variable empty, and set the ADDR.
Now if the port number exists in the input string, I can use this regex:
ORI_STR="connect single-cluster --listen-addr=127.0.0.1:12345 --filename=hello"
LISTEN_ADDR_REGEX="(^|[[:space:]])--listen-addr=(([^[:space:]] ):([^[:space:]] ))($|[[:space:]])"
[[ $ORI_STR =~ $LISTEN_ADDR_REGEX ]] && ADDR=${BASH_REMATCH[3]} && PORT=${BASH_REMATCH[4]}
echo "ADDR=$ADDR"
echo "PORT=$PORT"
This gives me:
ADDR=127.0.0.1
PORT=12345
But I don't know how to include the case that the port number is not set in the original string. (i.e. there's no :12345 in the ORI_STR).
CodePudding user response:
This works with or without the port:
LISTEN_ADDR_REGEX="(^|[[:space:]])--listen-addr=(([^[:space:]:] )(:([^[:space:]] ))?)($|[[:space:]])"
# ^ ^ ^^
[[ $ORI_STR =~ $LISTEN_ADDR_REGEX ]] && ADDR=${BASH_REMATCH[3]} && PORT=${BASH_REMATCH[5]}
# ^
echo "ADDR=$ADDR"
echo "PORT=$PORT"
I added parentheses around the :port part and marked it optional with ?. That moved the port from match group 4 to 5. I also added : to the exclusion list for the IP address; without that the IP was greedily matching the port.
It's kind of hard to spot the differences so I marked them with ^ carets.
CodePudding user response:
A ? means zero or one match.
#!/usr/bin/env bash
#ori_str="connect single-cluster --listen-addr=127.0.0.1:12345 --filename=hello"
ori_str="connect single-cluster --listen-addr=127.0.0.1 --filename=hello"
listen_addr_regex="^.* --listen-addr=([^:] )(:)?([^[:space:]] )? .*$"
[[ $ori_str =~ $listen_addr_regex ]] && addr=${BASH_REMATCH[1]} && port=${BASH_REMATCH[3]}
echo "addr=$addr"
echo "port=$port"
- Use
"${port:-none}"to usenoneas the default value or changenoneto something else if needed
