[英]Deleting leading spaces is not working in Bash
I have a string in Bash which may or may not start with any number of leading spaces, eg我在 Bash 中有一个字符串,它可能以也可能不以任意数量的前导空格开头,例如
" foo bar baz"
" foo bar baz"
"foo bar baz"
I want to delete the first instance of "foo" from the string, and any leading spaces (there may not be any).我想从字符串中删除“foo”的第一个实例,以及任何前导空格(可能没有)。
Following the advice from this question , I have tried the following:按照这个问题的建议,我尝试了以下方法:
str=" foo bar baz"
regex="[[:space:]]*foo"
echo "${str#$regex}"
echo "${str#[[:space:]]*foo}"
If str has one or more leading spaces, then it will return the result I want, which is _bar baz
(underscore = leading space).如果str有一个或多个前导空格,那么它将返回我想要的结果,即
_bar baz
(下划线=前导空格)。 If the string has no leading spaces, it won't do anything and will return foo bar baz
.如果字符串没有前导空格,它将不执行任何操作并返回
foo bar baz
。 Both 'echoes' return the same results here.两个“回声”在这里返回相同的结果。
My understanding is that using *
after [[:space:]]
should match zero or more instances of [[:space:]], not one or more.我的理解是在
[[:space:]]
之后使用*
应该匹配零个或多个 [[:space:]] 实例,而不是一个或多个。 What am I missing or doing wrong here?我在这里错过了什么或做错了什么?
EDITS编辑
@Raman - I've tried the following, and they also don't work: @Raman - 我尝试了以下方法,但它们也不起作用:
echo "${str#[[:space:]]?foo}"
echo "${str#?([[:space:]])foo}"
echo "${str#*([[:space:]])foo}"
All three solutions will not delete 'foo' whether or not there is a trailing space.无论是否有尾随空格,所有三个解决方案都不会删除“foo”。 The only solution that kind of works is the one I posted with the asterisk - it will delete 'foo' when there is a trailing space, but not when there isn't.
唯一可行的解决方案是我用星号发布的解决方案 - 当有尾随空格时它将删除“foo”,但在没有尾随空格时不会删除。
The best thing to do is to use parameter expansions (with extended globs) as follows:最好的办法是使用参数扩展(带有扩展的 glob),如下所示:
# Make sure extglob is enabled
shopt -s extglob
str=" foo bar baz"
echo "${str##*([[:space:]])}"
This uses the extended glob *([[:space:]])
, and the ##
parameter expansion (greedy match).这使用扩展的 glob
*([[:space:]])
和##
参数扩展(贪婪匹配)。
Edit.编辑。 Since your pattern has the suffix
foo
, you don't need to use greedy match:由于您的模式具有后缀
foo
,因此您不需要使用贪婪匹配:
echo "${str#*([[:space:]])foo}"
is enough.足够的。
Note.笔记。 you can put
foo
in a variable too, but just be careful, you'll have to quote it:您也可以将
foo
放入变量中,但要小心,您必须引用它:
pattern=foo
echo "${str#*([[:space:]])"$pattern"}"
will work.将工作。 You have to quote it in case the expansion of
pattern
contains glob characters.如果
pattern
的扩展包含全局字符,则必须引用它。 For example when pattern="foo[1]"
.例如当
pattern="foo[1]"
。
My understanding is that using * after [[:space:]] should match zero or more instances of [[:space:]], not one or more
我的理解是在 [[:space:]] 之后使用 * 应该匹配零个或多个 [[:space:]] 实例,而不是一个或多个
That's wrong.那是错误的。
What am I missing
我错过了什么
That glob is not regex .那个glob不是regex 。 In regex
*
matches zero or more preceding characters or groups.在正则表达式中
*
匹配零个或多个前面的字符或组。 In glob *
matches anything.在 glob
*
中匹配任何东西。 It's the same as for filename expansion, think along ls [[:space:]]*foo
.这与文件名扩展相同,请考虑
ls [[:space:]]*foo
。
You can use extended bash glob and do:您可以使用扩展的 bash glob 并执行以下操作:
shopt -s extglob
str=' foo bar baz'
echo "${str#*([[:space:]])foo}"
To do anything more complicated, actually use a regex.要执行更复杂的操作,请实际使用正则表达式。
str=' foo bar baz';
[[ $str =~ ^[[:space:]]*foo(.*) ]];
echo "${BASH_REMATCH[1]}"
If what you want is a real regex match, you should be using a real regex match:如果您想要的是真正的正则表达式匹配,您应该使用真正的正则表达式匹配:
$: [[ "$str" =~ [[:space:]]*(.*) ]]
$: echo "[${BASH_REMATCH[1]}]"
[foo bar baz]
A more pedestrian approach would be to skip the quotes.一种更简单的方法是跳过引号。
$: echo "[$str]"
[ foo bar baz]
$: new=$( echo $str )
$: echo "[$new]"
[foo bar baz]
Be aware that this opens you up to all sorts of messes in any more complex situations.请注意,在任何更复杂的情况下,这会让您面临各种混乱。 It breaks if you wanted to preserve more than a single consecutive space between values, or a tab instead of just a quote, etc.
如果您想在值之间保留多个连续的空格,或者一个制表符而不是引号等,它会中断。
$: str=' foo bar'$'\t''baz';
$: echo "[$str]"
[ foo bar baz]
$: new=$( echo $str )
$: echo "[$new]"
[foo bar baz]
It can cause other sorts of havoc too, but it's good to know the trick for the cases when it's appropriate.它也可能导致其他类型的破坏,但是在适当的情况下了解这些情况的诀窍是很好的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.