5

This question already has an answer here:

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.

marked as duplicate by Isaac, Hauke Laging bash Apr 3 '18 at 5:02

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

9

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
  • @Kusalananda Oh, sorry, when I saw your answer it had a different expansion ("${numbers%%.*}") which gives a different output (901). – nxnev Apr 2 '18 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. – Kusalananda Apr 2 '18 at 8:21
4
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.

  • printf "%.1s" 1234 should do, without needing the cut – ilkkachu Apr 2 '18 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

  • so the above code is correct? it's not working for me though, im using a bash script – Rashad Apr 2 '18 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! – Ned64 Apr 2 '18 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. – Kusalananda Apr 2 '18 at 8:16
2

With colrm

echo '901.32.02' | colrm 2
  • Using this simple method, is there a way to get the 2 last characters? Thanks – Kevin Lemaire Apr 10 at 6:33
  • @KevinLemaire with a know formatted string colrm 0 7. colrm don't handle negative number, perhaps in a future release. – ctac_ Apr 10 at 7:32
  • Ok. Thank you for the info – Kevin Lemaire Apr 10 at 8:25
0

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).

Not the answer you're looking for? Browse other questions tagged or ask your own question.