Reputation: 4373
Trying to remove leading and trailing blanks (SPC) from a variable's value using BASH, I feel that it does not work as described.
I started with ${var%% }
and ${var## }
which should remove the longest pattern, but it seems only one blank is removed:
% val=" a ";echo "|${val}|${val## }|"
| a | a |
% val=" a ";echo "|${val}|${val%% }|"
| a | a |
Then I tried pattern matching which seems no remove nothing (they also should repeatedly remove a blank at the start or end of the value):
% val=" a ";echo "|${val}|${val//# }|"
| a | a |
% val=" a ";echo "|${val}|${val//% }|"
| a | a |
I feel I made some simple mistake, but it seems I'm sitting on my eyes: Why doesn't this work?
(I did already visit these answers, but they did not include "my solution": How to trim whitespace from a Bash variable?, How to remove space from string?)
Upvotes: 1
Views: 131
Reputation: 4373
The problem is not that space (SPC) is handled specially; instead the problem is that pattern as used in the manual page of bash refers to pathname patterns, and not to regular expressions (unless extglob
is set (which seems to be set by default)). That is ' *'
is not a sequence of blanks, but instead it's a blank followed by anything.
The second problem is that "the longest matching pattern" is not determined by applying the match repeatedly until it fails, but only once. So if the pattern does not contain a *
, %
and %%
produce the same result, just as #
and ##
do).
The problems in ${val//# }
are:
//
and /#
cannot be combined; only one variant can be used.
pattern in ${parameter/pattern/string}
is not a regular expression, but a pathname pattern (still).
This means that there is no benefit of using ${val/# }
over using
${val# }
. To remove all leading and trailing blanks the following (somewhat complex) code can be used:
val=" a "
echo -n "|${val}"
while [ "_$val" != "_${val# }" ]
do
val="${val# }"
done
while [ "_$val" != "_${val% }" ]
do
val="${val% }"
done
echo "|${val}|"
So when using extglob
, the solution looks like this (as pointed out in a previous answer):
al=" c "
echo -n "|${val}"
val="${val##+( )}"
val="${val%%+( )}"
echo "|${val}|"
Upvotes: 0
Reputation: 20768
Space (0x20) is not special for both glob patterns and RE patterns.
For your problem I would take advantage of the extglob
shell option:
[STEP 108] # shopt -s extglob
[STEP 109] # v=' foo '
[STEP 110] # echo "|${v##+( )}|"
|foo |
[STEP 111] # echo "|${v%%+( )}|"
| foo|
[STEP 112] # echo "|${v%%+([[:blank:]])}|"
| foo|
[STEP 113] # echo "|${v##+([[:blank:]])}|"
|foo |
[STEP 114] #
Upvotes: 2
Reputation: 1032
You can archive this with sed
.
To remove all leading empty space and empty spaces on the end of a string ...
sed 's/^[ \t]*//;s/[ \t]*$//'
Upvotes: -1