Remove characters to right of first space in Bash
Solution 1
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.
Solution 2
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
Solution 3
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)
Solution 4
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).
Related videos on Youtube
Joshua Soileau
Updated on September 18, 2022Comments
-
Joshua Soileau almost 2 years
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:]]*}
-
Alexander about 6 yearsWill there never be leading whitespace?
-
notw86 about 6 yearsIf you are asking how to do it in bash you should probably not be using bash to do it. Use Perl or something.
-
-
Joshua Soileau about 6 yearsHow about if there is a leading space in the string? ` 2492 some string continues here`
-
Angel Todorov about 6 yearsThat will remove all the characters.
-
Angel Todorov about 6 years
[:space:]
character class includes space, tab, CR, NL, etc. So it's a catch-all for any whitespace. -
Digital Trauma about 6 years
a=($var); echo "${a[0]}"
also works for accessing the first word in the case of leading whitespace. -
Kusalananda about 6 yearsI think that's the first time I've seen anyone refer to regular expressions as "more robust" ;-)
-
Kusalananda about 6 years
-
Kusalananda about 6 yearsTry that with a string that starts with e.g.
*
. -
Robert Riedl about 6 years@Kusalananda tried it with
array=(*2492* *some * *string continues* here)
- still works -
Kusalananda about 6 yearsNow add a file in the current directory that contains
2492
in its name, for examplemyfile-2492.txt
, and run again. -
Robert Riedl about 6 years@Kusalananda oh wow, why does this happen ?
-
Kusalananda about 6 yearsFilename globbing happens when you create the array of unquoted strings.
-
Robert Riedl about 6 years@Kusalananda, I guess I'll have to start with
set -f
and end withset +f
? -
Kusalananda about 6 yearsThat would be one solution to it, yes. You should also quote the
${array[0]}
. -
anonymous at work about 6 yearsQuoted my strings, thanks for catching that @Kusalananda
-
MoonCheese62 about 6 yearsCould you please explain the purpose of
IFS
here?echo "${array[0]}"
, the only command between the assignment and deletion ofIFS
, doesn't include anything that would be subject to tokenization with the default setting but not withIFS=" "
or the other way around. -
gronostaj about 6 yearsI like this one. No regular expressions, no programming languages.