LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1477|回复: 8

请教一个奇怪的bash shell for loop问题

[复制链接]
发表于 2009-3-5 15:48:03 | 显示全部楼层 |阅读模式
内容
$ cat ./5.sh

#!/bin/bash
a="aaa ddd * ggg"
b="*"
for i in $a; do
if [ "$i" != "*" ]; then
echo "$i"
fi
done
#######################
if [ "$b" == "*" ]; then
echo "b: $b"
fi


运行
$ ./5.sh


aaa
ddd
1.sh
2.sh
2.txt
3.sh
5.sh
6.sh
b: *


如上,因为字符串中含有星号,在for循环中仍然执行了 echo *, 怎么这么奇怪呢?
发表于 2009-3-5 19:01:51 | 显示全部楼层
Post by freesatin;1956634
内容
  1. a="aaa ddd * ggg"
  2. for i in [color="Red"]$a[/color]; do
  3.     if [ "$i" != "*" ]; then
  4.         echo "$i"
  5.     fi
  6. done
复制代码
一试便知:
  1. a="aaa ddd * ggg"
  2. echo $a
复制代码
回复 支持 反对

使用道具 举报

发表于 2009-3-6 03:58:50 | 显示全部楼层
Post by freesatin;1956634
内容
$ cat ./5.sh

#!/bin/bash
a="aaa ddd * ggg"
b="*"
for i in $a; do
if [ "$i" != "*" ]; then
echo "$i"
fi
done
#######################
if [ "$b" == "*" ]; then
echo "b: $b"
fi


运行
$ ./5.sh


aaa
ddd
1.sh
2.sh
2.txt
3.sh
5.sh
6.sh
b: *


如上,因为字符串中含有星号,在for循环中仍然执行了 echo *, 怎么这么奇怪呢?
不能用双引号,要用单引号。*有转义,单引号取消转义,双引号不取消。
回复 支持 反对

使用道具 举报

发表于 2009-3-6 10:38:17 | 显示全部楼层
唉...fmying试过
  1. echo "*"
复制代码
吗?一来这不叫“转义”,二来双引号内的变量中含有的“*”不会被“扩展”为当前目录下的所有非隐藏文件。
回复 支持 反对

使用道具 举报

发表于 2009-3-7 21:45:09 | 显示全部楼层
echo "*"

echo '*'
的确不会,但是
  1. echo *
复制代码

  1. export a="*"
  2. echo $a
复制代码



  1. export a='*'
  2. echo $a
复制代码

都会
请问这是为什么呢?难道是echo自己会将变量中的*自动变成当前目录下所有隐藏文件?或者就是变量设定的时候会自动扩展*?
回复 支持 反对

使用道具 举报

发表于 2009-3-7 23:04:33 | 显示全部楼层
Post by fmying;1957542
请问这是为什么呢?难道是[color="Red"]echo自己会将变量中的*自动变成当前目录下所有[color="Red"]隐藏文件?或者就是变量设定的时候会自动扩展*?

呃哦,echo自己可不会扩展,都是shell做的(手误吧?);*可不会扩展出当前目录下的隐藏文件。如果你纠正一下你的提问,那么答案就是你所说的前一种情况。

熟悉bash的命令行处理的扩展顺序(如果你读过O'Reilly的Learning the bash Shell的ch7应该会记得里面有张复杂的命令行处理顺序流图,不过要完全记住不太可能)。

如果没看过,或者忘记了处理细节,那也没有关系,看bash手册页也可以学习和参考,没那么直观而已:
  1. EXPANSION
  2.        Expansion is performed on the command line after it has been split into
  3.        words.  There are seven kinds of expansion performed: brace  expansion,
  4.        tilde  expansion,  parameter  and variable expansion, command substitu-
  5.        tion, arithmetic expansion, word splitting, and pathname expansion.
  6.        The order of expansions is: brace expansion, tilde  expansion,  parame-
  7.        ter,  variable  and arithmetic expansion and command substitution (done
  8.        in a left-to-right fashion), word splitting, and pathname expansion.
复制代码
顺序就是:

  • 扩展a{b,c}d这样的括号扩展;
  • 扩展~username为username家目录路径;
  • 扩展$打头的那些东西;
  • 对上述扩展后的结果进行分词;
  • 对重新分词后的命令行执行路径名扩展,就是我们在这里讨论的东西。
回复 支持 反对

使用道具 举报

发表于 2009-3-8 07:01:34 | 显示全部楼层
“隐藏文件”的确是手误,呵呵。
也就是说,是bash在执行
echo $a
的时候,自动将aa * bb中的*扩展成了当前目录下所有非隐藏文件,然后将此作为参数传递给echo,echo此时只是忠实地输出了bash交给它的那些参数而已?
回复 支持 反对

使用道具 举报

发表于 2009-3-8 14:56:08 | 显示全部楼层
双引号(weak quote) 中会扩展的只有 $
其余都是普通符号 除 ' ' \ ` 这三个外(单引号 后斜 键盘上跟~同键的豆点)

Post by fmying;1957628
“隐藏文件”的确是手误,呵呵。
也就是说,是bash在执行
echo $a
的时候,自动将aa * bb中的*扩展成了当前目录下所有非隐藏文件,然后将此作为参数传递给echo,echo此时只是忠实地输出了bash交给它的那些参数而已?

没错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-3-10 13:01:53 | 显示全部楼层
Hi, Thanks. Finally, 我用的是set -o noglob, 或者如果a= aaa * bbb,
把for i in $a ==========〉for i in "$a" ,再echo "$i" 也可以打出*。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表