1

I'm writing a short script to pull the price of bitcoin. The information will be piped into an i3block so that I can see the hourly price on my status bar - here is what I have so far.

#!/bin/bash
price=$(curl -s gbp.rate.sx/btc?T | tail -3 | head -1 | grep -o '[0-9]*' | cut -d ' ' -f1)
echo $price

I curl the bitcoin price (in £) from rate.sx with the T option (text only, no ANSI sequences), select the average price line using head and tail and grep out the numbers. The output looks something like this:

26563 26396 1738 8 6 29

The first number is the average price, with the others being the median, change, etc... As you can see, I pass this through cut with whitespace as the delimiter, but the output is uncut.

I also tried to swap whitespace for ',' to try convert the output to csv, but this failed also.

price=$(curl -s gbp.rate.sx/btc?T | tail -3 | head -1 | grep -o '[0-9]*' | sed 's/ /,/' )

The above also gave me the same output. Why are cut and sed struggling to recognise the whitespace?

kubanczyk
  • 1,258
  • 9
  • 19
Deez
  • 41
  • 5
  • 3
    If you execute curl -s gbp.rate.sx/btc?T | tail -3 | head -1 | grep -o '[0-9]*' you will notice that grep -o '[0-9]*' outputs each matching sequence of digits on a separate line – steeldriver Jan 17 '21 at 13:39
  • 2
    Are you just looking for the average price? (You don't actually say what output you want from your example.) If so, just use curl … | LC_ALL=C grep -Po '^avg:.*?\K[[0-9]+' I can explain this if it really does match what you want. – Chris Davies Jan 17 '21 at 13:41
  • Thank you, turned out the spaces were actually newlines! Fixed with: price=$(curl -s gbp.rate.sx/btc?T | tail -3 | head -1 | grep -o '[0-9]*' | cut -d$'\n' -f1) – Deez Jan 17 '21 at 13:54
  • @crystal_pepsi Isn't that cut command in your last comment just the same as head -1 again? – Kusalananda Jan 17 '21 at 15:18

2 Answers2

2

The issue that you're having with your own pipeline is that you don't realize that the output from grep is several lines long, with one integer on each line. The numbers are outputted on the same line only because you use $price unquoted.


If you want the average price, i.e. the amount after the avg: tag, then it would be easiest with awk:

curl -s 'https://gbp.rate.sx/btc?T' |
awk '/^avg:/ { print $2 }'

What the awk code above is doing is to print the second whitespace-delimited field from each line that starts with the text avg:.

This would give you something like £26421. Would you want that amount without the pound symbol, use print substr($2,2) in place of print $2.

Would you want to do this using grep and cut instead, then do something like

curl -s 'https://gbp.rate.sx/btc?T' |
grep '^avg:' | cut -d ' ' -f 2

To delete the pound symbol from this, just pipe this through either cut -c 2- or tr -d '£' at the end.

Note that to just output the result of this, there is no reason to first put it in a variable.

Kusalananda
  • 333,661
  • Thanks, I should say that the only reason I have this as a variable is because occasionally i3blocks messes up with these sort of scripts. I wrote a very similar script curling wttr.in weather info to a block and the block simply would not work unless I echo'd the output as a variable for some reason. – Deez Jan 17 '21 at 16:14
0

The output looks something like this:

echo $price
26563 26396 1738 8 6 29

That's because $price is unquoted, which makes the shell split it on whitespace. echo gets multiple arguments, which it joins with single spaces.

See e.g.: When is double-quoting necessary?

ilkkachu
  • 138,973