5

Let's say the variable numbers=$@ where $@is from user input. The user typed in ./script.sh 901.32.02 and I want to get the first digit 9 and store in another variable. How can I do this? I was told to do

 for n in `seq 1 $count` do var=${numbers[0]} done 

but that prints out the whole input if I echo $var instead of just 9.

1

5 Answers 5

14

In Bash, you can extract the first character using parameter expansion:

${parameter:offset:length} 

Example:

$ var=901.32.02 $ first_char="${var:0:1}" $ echo "${first_char}" 9 
2
  • @Kusalananda Oh, sorry, when I saw your answer it had a different expansion ("${numbers%%.*}") which gives a different output (901). Commented Apr 2, 2018 at 8:19
  • Ah, yes, because I interpreted "number" as "number" rather than "digit" before I saw my error. Ah well, I'll remove that comment anyway as you added the generic form of the expansion too. Commented Apr 2, 2018 at 8:21
5
numbers='901.32.02' firstdigit="${numbers:0:1}" printf 'The first digit is "%s"\n' "$firstdigit" 

The result of the above is

The first digit is "9" 

The ${numbers:0:1} parameter expansion in bash give you the substring of length 1 from the start of the string (offset zero). This is a bash-specific parameter substitution (also in some other shells, but not in the POSIX standard).

In a POSIX shell, you may also do

firstdigit=$( printf "%s\n" "$numbers" | cut -c 1 ) 

This will use cut to only return the first character.

Or, using standard parameter expansions,

firstdigit="${numbers%${numbers#?}}" 

This first uses ${numbers#?} to create a string with the first digit removed, then it removes that string from the end of $numbers using ${numbers%suffix} (where suffix is the result of the first expansion).


The above assumes that the first character of $numbers is actually a digit. If it is not, then you would have to first remove non-digits from the start of the value:

numbers=$( printf '%s\n' "$numbers" | sed 's/^[^0-9]*//' ) 

or,

numbers="${numbers#${numbers%%[0-9]*}}" 

${numbers[0]} would have worked if each character was a separate element in the array numbers (and if the first character was a digit). Since numbers is not an array, it's equivalent to just $numbers.

1
  • printf "%.1s" 1234 should do, without needing the cut Commented Apr 2, 2018 at 11:35
3

You can use below method too

cat script.sh #!/bin/bash echo $1 | awk '{print substr($1,1,1)}' sh script.sh 90 Where 90 is the user input 

output is 9

3
  • so the above code is correct? it's not working for me though, im using a bash script Commented Apr 2, 2018 at 4:44
  • @Rashad Yes, you can easily call the external program awk from your bash script and store the results in a bash script variable! Commented Apr 2, 2018 at 8:16
  • Note also that the #!-line must not be preceded by blank lines or spaces. You are also specifying bash as the script language in the script itself, while running it with sh. Commented Apr 2, 2018 at 8:16
2

With colrm

echo '901.32.02' | colrm 2 
2
  • Using this simple method, is there a way to get the 2 last characters? Thanks Commented Apr 10, 2019 at 6:33
  • @KevinLemaire with a know formatted string colrm 0 7. colrm don't handle negative number, perhaps in a future release. Commented Apr 10, 2019 at 7:32
1

If you want to detect only digits (not other character types) you should use a simple regular expression.

[[ ${numbers} =~ ^([[:digit:]]) ]] && var=${BASH_REMATCH[1]} 

In $var is a digit or it is empty (even not declared).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.