Linux-bash-if-elif-don';I don’我没有按预期工作

Linux-bash-if-elif-don';I don’我没有按预期工作,linux,bash,Linux,Bash,根据变量的开头,我的Bash脚本必须做一些不同的事情。 当我运行以下脚本时: #!/bin/bash line="__B something" if [ -n $(echo "$line" | grep "^__A") ]; then echo "Line __A" elif [ -n $(echo "$line" | grep "^__B") ]; then echo "Line __B" elif [ -n $(echo "$line" | grep "^__C") ]; t

根据变量的开头,我的Bash脚本必须做一些不同的事情。 当我运行以下脚本时:

#!/bin/bash

line="__B something"

if [ -n $(echo "$line" | grep "^__A") ]; then
   echo "Line __A"
elif [ -n $(echo "$line" | grep "^__B") ]; then
   echo "Line __B"
elif [ -n $(echo "$line" | grep "^__C") ]; then
   echo "Line __C"
elif [ -n $(echo "$line" | grep "^__D") ]; then
   echo "Line __D"
elif [ -n $(echo "$line" | grep "^__E") ]; then
   echo "Line __E"
elif [ $(echo "$line" | grep "^__F") ]; then
   echo -n "Line __F"
else
   echo "something other"
fi
Bash无法识别字符串以_B开头:

输出为:

Line __A
我的剧本怎么了?
谢谢你的帮助

我认为这与在bash if条件中使用
[[
[
之间的细微差别有关

您可以在任何地方使用
[[
]
(似乎有效),例如

或者你可以这样引用subshell

if [ -n "$(echo '$line' | grep '^__A')" ]; then
   echo "Line __A"
[[
的惊喜更少,使用起来更安全。但事实并非如此 portable-Posix没有指定它的功能,只指定了一些shell 支持它(除了bash之外,我听说ksh也支持它), 你能行

[[-e$b]]

要测试文件是否存在。但是使用
[
,您必须引用
$b
, 因为它拆分参数并展开类似于
“a*”
(其中
[[
这也与
[
如何成为外部代码有关 程序,并像其他程序一样正常地接收其参数 程序(虽然它也可以是一个内置的,但它仍然没有 这是一种特殊的处理方法)


根据这里关于stackoverflow的回答。所以在您的例子中,bash很可能是在一个空格中分隔字符串,这有一些副作用。

我认为这与在bash if条件中使用
[[
[
之间的细微差别有关

您可以在任何地方使用
[[
]
(似乎有效),例如

或者你可以这样引用subshell

if [ -n "$(echo '$line' | grep '^__A')" ]; then
   echo "Line __A"
[[
的惊喜更少,使用起来更安全。但事实并非如此 portable-Posix没有指定它的功能,只指定了一些shell 支持它(除了bash之外,我听说ksh也支持它), 你能行

[[-e$b]]

要测试文件是否存在。但是使用
[
,您必须引用
$b
, 因为它拆分参数并展开类似于
“a*”
(其中
[[
这也与
[
如何成为外部代码有关 程序,并像其他程序一样正常地接收其参数 程序(虽然它也可以是一个内置的,但它仍然没有 这是一种特殊的处理方法)


根据这里关于stackoverflow的回答。因此,在您的情况下,bash很可能在空格中分隔字符串,这会产生一些副作用。

如果您使用
xtrace
选项运行脚本,您可以看到发生了什么:

bash -x your-script
+ line='__B something'
++ echo '__B something'
++ grep '^__A'
+ '[' -n ']'
+ echo 'Line __A'
Line __A
因为您使用了旧的
测试
内置(也称为
[
),所以扩展已完成,但除了
-n
之外,没有任何测试结果。使用
[
关键字将正确引用内容:

bash -x your-script
+ line='__B something'
++ echo '__B something'
++ grep '^__A'
+ [[ -n '' ]]
++ echo '__B something'
++ grep '^__B'
+ [[ -n __B something ]]
+ echo 'Line __B'
Line __B
但是,使用外部程序
grep
是一种浪费。最近版本的
bash
内置了正则表达式(REs)(使用绑定操作符
=~
),但您不需要REs。在这种情况下,简单的全局搜索可以:

#!/bin/bash

line="__B something"

if [[ $line == __A* ]]; then
   echo "Line __A"
elif [[ $line == __B* ]]; then
   echo "Line __B"
elif [[ $line == __C* ]]; then
   echo "Line __C"
elif [[ $line == __D* ]]; then
   echo "Line __D"
elif [[ $line == __E* ]]; then
   echo "Line __E"
elif [[ $line == __F* ]]; then
   echo -n "Line __F"
else
   echo "something other"
fi

如果使用
xtrace
选项运行脚本,则可以看到发生了什么:

bash -x your-script
+ line='__B something'
++ echo '__B something'
++ grep '^__A'
+ '[' -n ']'
+ echo 'Line __A'
Line __A
因为您使用了旧的
测试
内置(也称为
[
),所以扩展已完成,但除了
-n
之外,没有任何测试结果。使用
[
关键字将正确引用内容:

bash -x your-script
+ line='__B something'
++ echo '__B something'
++ grep '^__A'
+ [[ -n '' ]]
++ echo '__B something'
++ grep '^__B'
+ [[ -n __B something ]]
+ echo 'Line __B'
Line __B
但是,使用外部程序
grep
是一种浪费。最近版本的
bash
内置了正则表达式(REs)(使用绑定操作符
=~
),但您不需要REs。在这种情况下,简单的全局搜索可以:

#!/bin/bash

line="__B something"

if [[ $line == __A* ]]; then
   echo "Line __A"
elif [[ $line == __B* ]]; then
   echo "Line __B"
elif [[ $line == __C* ]]; then
   echo "Line __C"
elif [[ $line == __D* ]]; then
   echo "Line __D"
elif [[ $line == __E* ]]; then
   echo "Line __E"
elif [[ $line == __F* ]]; then
   echo -n "Line __F"
else
   echo "something other"
fi

看起来你错放了最后一个
-n
使用更多的引号!
如果[-n”$(echo…);那么
。引用参数扩展!(但你的设计非常糟糕)。@gniourf\u gniourf:如果你尝试双引号引用整个
echo | grep
命令(不仅仅是你显示的剪报)你会发现它并不是那么简单,特别是考虑到
$line
@cdarke中的嵌入空间:
$line
中的嵌入空间如何?@OP:这将是
case
的典型用法!
case$line in(u a*)echo“line”;(u B*)echo“line”;(*)echo“line”;(*)echo“other”;esac
。看起来你错放了最后一个
-n
使用了更多的引号!
如果[-n$(echo…);那么
。引用参数扩展!(但是你的设计很糟糕)。@gniourf\u gniourf:如果你试图双引号引用整个
echo | grep
命令(不仅仅是你显示的snip)你会发现它并不那么简单,特别是考虑到
$line
@cdarke中的嵌入空间:
$line
中的嵌入空间如何?@OP:这将是
案例
的典型用法!
案例$line in(u a*)echo“line”;(u B*)echo“line”;(*)echo“line”;(*)echo“line”;(*)echo“other”;