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:]]*}
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:]]*}
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.
2492 some string continues here
– Joshua Soileau
Apr 12 '18 at 20:56
[:space:]
character class includes space, tab, CR, NL, etc. So it's a catch-all for any whitespace.
– glenn jackman
Apr 12 '18 at 22:36
a=($var); echo "${a[0]}"
also works for accessing the first word in the case of leading whitespace.
– Digital Trauma
Apr 12 '18 at 22:52
set -f
first
– glenn jackman
Apr 12 '18 at 22:58
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.
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
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)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).
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
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
array=(*2492* *some * *string continues* here)
- still works
– Robert Riedl
Apr 13 '18 at 07:21
2492
in its name, for example myfile-2492.txt
, and run again.
– Kusalananda
Apr 13 '18 at 07:23
set -f
and end with set +f
?
– Robert Riedl
Apr 13 '18 at 07:37
${array[0]}
.
– Kusalananda
Apr 13 '18 at 07:39
IFS
here? echo "${array[0]}"
, the only command between the assignment and deletion of IFS
, doesn't include anything that would be subject to tokenization with the default setting but not with IFS=" "
or the other way around.
– David Foerster
Apr 13 '18 at 11:05