求帮助,12.10,判断符号[]在shell中用法。

sh/bash/dash/ksh/zsh等Shell脚本
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

求帮助,12.10,判断符号[]在shell中用法。

#1

帖子 super_art » 2014-10-09 16:41

学习写一个小demo:
我read一个变量,$yn,判断[ "$yn" == "Y"]时报错,unexpected operator。
应该是==两边的空格造成的运算符识别不了。
但是我在bash命令里直接执行没有问题,而且我看鸟哥私房菜也强调必须有空格。我感觉是自己的环境配置有问题,但是新接触Linux,无从下手。
求帮助,求指导。

另外:
我直接命令行执行[ "$yn"=="Y" ],不管括号里写什么变量判断,执行返回值都是0,那我没有空格的语句到底执行了什么操作?求指点。
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 求帮助,12.10,判断符号[]在shell中用法。

#2

帖子 cao627 » 2014-10-09 18:19

没有空格就没有比较,括号里什么也没有执行,只是非空而已,非空就是肯定的判断。
比如

代码: 全选

czj@sun:~$ [  ]&&echo "yes"
czj@sun:~$ [ 0 ]&&echo "yes"
yes
头像
susbarbatus
帖子: 2966
注册时间: 2010-04-10 16:14
系统: Arch Linux

Re: 求帮助,12.10,判断符号[]在shell中用法。

#3

帖子 susbarbatus » 2014-10-09 19:31

[ "$yn" == "Y"] 报错只是因为 ] 前面没加空格吧……
沉迷将棋中……
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#4

帖子 super_art » 2014-10-10 9:01

susbarbatus 写了:[ "$yn" == "Y"] 报错只是因为 ] 前面没加空格吧……
这是我发帖手打错的,文件里有空格。
而且提示会说哪儿出错,不是期望的运算符。unexpected operator提示的就是$yn赋值处,双等号之前。
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#5

帖子 super_art » 2014-10-10 9:02

cao627 写了:没有空格就没有比较,括号里什么也没有执行,只是非空而已,非空就是肯定的判断。
比如

代码: 全选

czj@sun:~$ [  ]&&echo "yes"
czj@sun:~$ [ 0 ]&&echo "yes"
yes
受教,谢谢。
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 求帮助,12.10,判断符号[]在shell中用法。

#6

帖子 astolia » 2014-10-10 9:55

4楼,]前面没加空格报的错是missing ]

这个问题实际上有点复杂。

首先[或test命令有两种情况,一种是coreutils包里的独立程序,另外一种是某些shell(比如bash)的内置命令
两者在细节上有所不同。你可以用

代码: 全选

type [
来看到你输入的[或test到底是那种

如果是独立程序版的,可以通过manpage来看

代码: 全选

man [
……
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
-z STRING
the length of STRING is zero
STRING1 = STRING2
the strings are equal
STRING1 != STRING2
the strings are not equal
……
上面第一处红字部分明确说明了如果仅仅是一个字符串,等价于用-n来判断字符串是否为空。所以,在独立程序的[或test看来,[ "$yn"=="Y" ]就是判断"$yn"=="Y"这个字符串是否为空。记住字符串并不需要用"或'整体包起来,只包部分也可以的。
第二处红字说明了判断字符串相等要用=,而并没有提到==的用法。不过呢,实际上还是要看程序版本。manpage最后的SEE ALSO提到了一句info coreutils 'test invocation',你可以用这个来看进一步的信息。
如果info的输出中有
* String tests:: -z -n = == !=
说明支持==比较
如果是
* String tests:: -z -n = !=
说明不支持==比较
我稍微测试了一下,ubuntu 10.04的coreutils包版本是7.4,不支持==。ubuntu 12.04 LTS是8.13,支持==。你可以用

代码: 全选

/usr/bin/[ --version
来看程序的版本号


如果是shell内置的命令,就要查shell的manpage了,以bash为例

代码: 全选

man bash
SHELL BUILTIN COMMANDS一节中的说明摘抄如下
test expr
[ expr ]
Return a status of 0 (true) or 1 (false) depending on the evalu‐
ation of the conditional expression expr. Each operator and op‐
erand must be a separate argument. Expressions are composed of
the primaries described above under CONDITIONAL EXPRESSIONS.
test does not accept any options, nor does it accept and ignore
an argument of -- as signifying the end of options.
叫你去看CONDITIONAL EXPRESSIONS。CONDITIONAL EXPRESSIONS一节中又有如下内容
string
-n string
True if the length of string is non-zero.

string1 == string2
string1 = string2
True if the strings are equal. = should be used with the test
command for POSIX conformance. When used with the [[ command,
this performs pattern matching as described above (Compound Com‐
mands).
同样说单独的字符串等价于用-n判断。但bash内置的[或test命令=和==两种比较都支持

所以估计楼主用的是较低版本的独立程序版[,不支持==比较
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 求帮助,12.10,判断符号[]在shell中用法。

#7

帖子 eexpress » 2014-10-10 10:00

只记得-z -n ,一个需要[[]],一个需要[],这点bt。
● 鸣学
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#8

帖子 super_art » 2014-10-10 10:03

找到一个解决方法,“==”换“=”。

嗯,test或[] 在正常bash里检测字符串用“=”和“==”效果是一样的。但是shell文件里“==”失效。

出于程序员的习惯,习惯了“==”判断。我看的学习资料,也是在shell文件里写的"==",也没说有问题。

感觉是环境变量的差异。

感谢两位的回答。
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#9

帖子 super_art » 2014-10-10 10:14

astolia 写了:4楼,]前面没加空格报的错是missing ]

这个问题实际上有点复杂。

首先[或test命令有两种情况,一种是coreutils包里的独立程序,另外一种是某些shell(比如bash)的内置命令
两者在细节上有所不同。你可以用

代码: 全选

type [
来看到你输入的[或test到底是那种

如果是独立程序版的,可以通过manpage来看

代码: 全选

man [
……
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
-z STRING
the length of STRING is zero
STRING1 = STRING2
the strings are equal
STRING1 != STRING2
the strings are not equal
……
上面第一处红字部分明确说明了如果仅仅是一个字符串,等价于用-n来判断字符串是否为空。所以,在独立程序的[或test看来,[ "$yn"=="Y" ]就是判断"$yn"=="Y"这个字符串是否为空。记住字符串并不需要用"或'整体包起来,只包部分也可以的。
第二处红字说明了判断字符串相等要用=,而并没有提到==的用法。不过呢,实际上还是要看程序版本。manpage最后的SEE ALSO提到了一句info coreutils 'test invocation',你可以用这个来看进一步的信息。
如果info的输出中有
* String tests:: -z -n = == !=
说明支持==比较
如果是
* String tests:: -z -n = !=
说明不支持==比较
我稍微测试了一下,ubuntu 10.04的coreutils包版本是7.4,不支持==。ubuntu 12.04 LTS是8.13,支持==。你可以用

代码: 全选

/usr/bin/[ --version
来看程序的版本号


如果是shell内置的命令,就要查shell的manpage了,以bash为例

代码: 全选

man bash
SHELL BUILTIN COMMANDS一节中的说明摘抄如下
test expr
[ expr ]
Return a status of 0 (true) or 1 (false) depending on the evalu‐
ation of the conditional expression expr. Each operator and op‐
erand must be a separate argument. Expressions are composed of
the primaries described above under CONDITIONAL EXPRESSIONS.
test does not accept any options, nor does it accept and ignore
an argument of -- as signifying the end of options.
叫你去看CONDITIONAL EXPRESSIONS。CONDITIONAL EXPRESSIONS一节中又有如下内容
string
-n string
True if the length of string is non-zero.

string1 == string2
string1 = string2
True if the strings are equal. = should be used with the test
command for POSIX conformance. When used with the [[ command,
this performs pattern matching as described above (Compound Com‐
mands).
同样说单独的字符串等价于用-n判断。但bash内置的[或test命令=和==两种比较都支持

所以估计楼主用的是较低版本的独立程序版[,不支持==比较

谢谢!
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 求帮助,12.10,判断符号[]在shell中用法。

#10

帖子 astolia » 2014-10-10 10:19

super_art 写了:找到一个解决方法,“==”换“=”。

嗯,test或[] 在正常bash里检测字符串用“=”和“==”效果是一样的。但是shell文件里“==”失效。

出于程序员的习惯,习惯了“==”判断。我看的学习资料,也是在shell文件里写的"==",也没说有问题。

感觉是环境变量的差异。

感谢两位的回答。
别在那里瞎感觉,写程序不是靠感觉的。
你在脚本开头肯定写的是#! /bin/sh,你自己ls -l /bin/sh看看那个是不是bash。
dash内置的test支不支持==你自己man dash看
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#11

帖子 super_art » 2014-10-11 10:19

astolia 写了:
super_art 写了:找到一个解决方法,“==”换“=”。

嗯,test或[] 在正常bash里检测字符串用“=”和“==”效果是一样的。但是shell文件里“==”失效。

出于程序员的习惯,习惯了“==”判断。我看的学习资料,也是在shell文件里写的"==",也没说有问题。

感觉是环境变量的差异。

感谢两位的回答。
别在那里瞎感觉,写程序不是靠感觉的。
你在脚本开头肯定写的是#! /bin/sh,你自己ls -l /bin/sh看看那个是不是bash。
dash内置的test支不支持==你自己man dash看

我的coreutils也是8.13。dash里的test expression 字符串比较只提到了=
可是我脚本开头是照着鸟哥私房菜书里写的,是#!/bin/bash ……
可我看man bash 字符串比较同时提到了 = 和 ==
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 求帮助,12.10,判断符号[]在shell中用法。

#12

帖子 astolia » 2014-10-11 11:35

你可以把你写的脚本传上来看看
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#13

帖子 super_art » 2014-10-11 13:54

虚拟机里,还不会直接复制文件到实际的windows系统里,手敲的,看了一下,应该没有敲错的。

代码: 全选

#!/bin/bash
# Program:
#     This program shows the user's choice
# History:
#     2014/10/09 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N) : " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt" && exit 0
echo "I don't know what your choice is " && exit 0
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 求帮助,12.10,判断符号[]在shell中用法。

#14

帖子 astolia » 2014-10-11 15:36

你是怎么执行这个脚本的?
sh xxx
bash xxx
./xxx
是哪种?
super_art
帖子: 9
注册时间: 2014-10-09 16:23
系统: win8.1 pro

Re: 求帮助,12.10,判断符号[]在shell中用法。

#15

帖子 super_art » 2014-10-11 17:34

astolia 写了:你是怎么执行这个脚本的?
sh xxx
bash xxx
./xxx
是哪种?
我是用的sh,从练习开始,一直用的这个。
刚才试了一下,是我执行的不对。bash执行, == 判断正常。
./ 执行报错permission denied 。我对当前目录是 drwxrwxr-x,对文件是-rw-rw-r--,我尝试改一下。
感谢指点。

再问大神一个问题,我在之前看书时,说用source执行后,变量会导入到父进程。可是我执行的时候。read完变量,直接退出到了登录界面。
我也切换过root来执行,也被退了。
man source 没有,type 说是a shell builtin。不懂。
回复