9
2492  some string continues here

I would like to convert this to

2492

in Bash. How would I go about that?

This feels close, but is not working:

var="2492  some string continues here  "
echo ${var%[[:space:]]*}

6 Answers6

15

Because there are multiple spaces you want to use

${var%%[[:space:]]*}
# ...^^

to remove the longest trailing substring that starts with a space

With just a single % you're removing the shortest sequence of a space followed by zero or more characters, which is just the last space in the string.

$ echo ">$var<"; echo ">${var%[[:space:]]*}<"; echo ">${var%%[[:space:]]*}<"
>2492  some string continues here  <
>2492  some string continues here <
>2492<

If you're just looking for the first word, you can do this:

read -r word rest_of_string <<<"$var"
echo "I have: $word"

That will take care of leading whitespace, assuming you have not altered the IFS variable.

glenn jackman
  • 85,964
4

There is the simple solution of using %% (${var%% *})instead of % (${var% *}). That will remove everything (*) after an initial space.

$ var='2492  some string continues here'
$ echo "${var%% *}"
2492

But that will fail if the string in var has any leading spaces. It is possible to remove the leading spaces with:

$ var=$' \t 2492  some string continues here  '
$ var="${var#"${var%%[![:space:]]*}"}"
$ echo "$var"
2492  some string continues here  
$ echo "${var%%[[:space:]]*}"
2492

That works even if the white-spaces are spaces tabs NL or CR.


Regex

Maybe a more robust solution is to use a regex:

$ var=$' \t 2492  some string continues here  '
$ regex='^[[:space:]]*([^[:space:]]+)'
$ [[ $var =~ $regex ]] && var=${BASH_REMATCH[1]}
$ echo "$var"
2492
2

You can also use the simple tool cut, who cuts strings based on a delimiter :

echo "$mystring" | cut -d' ' -f 1 

Where :

  • -d' ' sets the delimiter to a space
  • -f 1 gives the first field (based on the delimiter)
Ikaros
  • 882
1

You can use native shell string manipulation:

TEST="test  1234 foo"
SPLIT_VAR=${TEST/ */ }

It will replace the first pattern matching " *" (one space then anything) and replace it with " " (one space). So you keep the first word and the first space.

You can see http://www.tldp.org/LDP/abs/html/string-manipulation.html for more usage of string manipulation.

And as a side note, it's also works less evolved shell (tested on busybox's ash implementation).

0

If you don't mind an external call, use awk or sed:

$ string="first second third fourth"
$ echo "${string}" | awk '{print $1}' # will work even with tabs
first
$ echo "${string}" | sed -e "s/ .*$//" # will fail on leading whitespace
first
0

To use only bash and builtin commands, you could use Internal Field Seperator(IFS) and arrays

set -f                # To prevent filename globbing when creating the array, as pointed out by Kusalananda in the comments
array=(2492 some string continues here)
set +f                # enable it again
IFS=" "
echo "${array[0]}"
unset IFS