简体   繁体   English

删除前导空格在 Bash 中不起作用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM