bash: using "cut -c" on the strings with spaces like " ?.?"

i just want to get the third char from watingForHDD. Any idea how to do this?

(my idea was to log some data about the used system capacity etc...)

#!/bin/bash
x="`top -d 1 -n 1`"
echo "$x"
waitingForHDD=`echo "$x" | head -n3 | tail -n1 | cut -d"," -f9,10`
echo "$waitingForHDD" #output(with 2 spaces in the beginning): 0,6 wa
b=`echo "$waitingForHDD" | cut -c3`
echo "$b" #output(i mean WTF? thats not even in waitingForHDD): B
0

2 Answers

The output of top uses formatting: In 0,6 wa, the 0,6 is in bold. Use batch mode (-b) to disable it:

$ top -bd 1 -n 1 | head -n3 | tail -n1 | cut -d, -f5 | cut -c3
1

(I am on a different locale, so the fields in the first cut differ.)

Try top -d 1 -n 1 | head -n3 | tail -n1 | cut -d, -f5 | less to see the special characters in action.

All that said, you might be better of using something like awk instead of this jumble of heads, tails and cuts.

As @muru pointed out, the problem is that top uses ANSI escape sequences to format its output. You can see this by piping through a program like od which will let you see non-printing characters. For example, this command prints the "wa" and "hi" fields of the 3rd line of top:

$ top -d 1 -n 1 | grep ^% | cut -d"," -f5,6

The output on my system is:

1.0 wa, 0.0 hi

Let's have a look at the non-printing characters:

$ top -d 1 -n 1 | grep ^% | cut -d"," -f5,6 | od -c
0000000 033 ( B 033 [ m 033 [ 3 9 ; 4 9 m 033 [
0000020 1 m 1 . 0 033 ( B 033 [ m 033 [
0000040 3 9 ; 4 9 m w a , 033 ( B 033 [ m 033
0000060 [ 3 9 ; 4 9 m 033 [ 1 m 0 . 0
0000100 033 ( B 033 [ m 033 [ 3 9 ; 4 9 m h
0000120 i \n
0000122

As you can see above, the third character is a B and that's what you're getting. So, assuming you want a script that i) prints all of top's output, ii) prints the "wa" and "hi" fields of the 3rd line and iii) prints the digits from the "wa" field, you could do something like:

#!/usr/bin/env bash
x="$(top -d 1 -n 1)"
echo "$x"
waitingForHDD=$(grep ^% <<<"$x" | cut -d"," -f5,6)
echo "$waitingForHDD"
b=$(grep -oP '^.*?\K[.\d]+(?= )' <<<"$waitingForHDD" )
echo "$b"

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like