0

I want to generate a comma separated ip values with mapped ports and create a string.

Here is my code:

zk_ip="['192.168.0.10', '192.168.0.20', '192.168.0.30']" zk_host="" for i in $zk_ip[@] do add=$(echo "$i:2181") zk_host="$zk_host $add" done echo $zk_host 

Output:

[192.168.0.10,:2181 192.168.0.20, :2181 192.168.0.30]:2181 

Expected ouptut:

192.168.0.10:2181, 192.168.0.20:2181, 192.168.0.30:2181 
3
  • Why this format for your list? It's not valid JSON due to the quote types, so I don't see it as a likely format for your input (or if it is, maybe serialized by Python, you can just use the json module to make it JSON, and then you can process it in bash with jq). Is there a reason you don't define it as zk_ip=( 192.168.0.10 192.168.0.20 192.168.0.30 ), which is the native format for defining a bash array? Commented Jun 25, 2018 at 15:05
  • 1
    ...to be clear, as JSON, this would be zk_ip='["192.168.0.10", "192.168.0.20", "192.168.0.30"]' -- note the single quotes on the outside and the double quotes on the inside. Commented Jun 25, 2018 at 15:07
  • (Also note that if you were using valid bash array syntax, you'd need to make it "${zk_ip[@]}" to iterate -- the curly braces are mandatory when you're using [@]). Commented Jun 25, 2018 at 15:10

3 Answers 3

2

So, you have a JSON-ish array that you want to modify (JSON strings are enclosed in double quotes).

I would use a JSON parser to manage this:

zk_ip="['192.168.0.10', '192.168.0.20', '192.168.0.30']" new_ip=$(echo "$zk_ip" | tr "'" '"' | jq -c 'map("\(.):2181")') echo "$new_ip" 
["192.168.0.10:2181","192.168.0.20:2181","192.168.0.30:2181"] 

If you want the output to not look like JSON, you can do:

new_ip=$(echo "$zk_ip" | tr "'" '"' | jq -r 'map("\(.):2181") | join(", ")') echo "$new_ip" 
192.168.0.10:2181, 192.168.0.20:2181, 192.168.0.30:2181 
Sign up to request clarification or add additional context in comments.

2 Comments

glenn Thanks for the answer! it works perfectly fine. Could you explain what q -r 'map("(.):2181") | join(", ")') does?
It's quite self-evident given the input and the output. jq is a tricky little functional language. That map function iterates over an array (the input string), applies the transformation to each element, and returns a new array. The join function should be obvious. The -r option is for "raw" output (not JSON-formatted data). See the jq info page.
1

You may use:

zk_ip="['192.168.0.10', '192.168.0.20', '192.168.0.30']"

zk_host="" for i in ${zk_ip//[][,\']/}; do zk_host+="$i:2181, " done echo "${zk_host%, }" 

192.168.0.10:2181, 192.168.0.20:2181, 192.168.0.30:2181 

3 Comments

Is there a way to convert "['192.168.0.10', '192.168.0.20', '192.168.0.30']" to ('192.168.0.10' '192.168.0.20' '192.168.0.30')? Because the shell script is passed zk_host as parameter
You mean zk_ip value as shown in question is passed from some other script?
Yes you are correct. The shell script is rendered using terraform in which zk_ip is passed as a list of strings
0

Assuming that you have your IP addresses in an array, such as

zk_ip=( '192.168.0.10' '192.168.0.20' '192.168.0.30' ) 

then,

( IFS=','; printf '%s\n' "${zk_ip[*]/%/:2181}" ) 

would print

192.168.0.10:2181,192.168.0.20:2181,192.168.0.30:2181 

Setting IFS makes "${zk_ip[*]}" expand to a comma-delimited string with all the entries of the array. With /%/:2181 each element is suffixed with the string :2181 before printing.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.