免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: li2002
打印 上一主题 下一主题

关于IFS的疑问  关闭 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2005-03-17 22:41 |只看该作者

关于IFS的疑问

看了aerofox说明觉得有些道理,感谢!!
不过我把这个拿到sco unix(/bin/sh)下做试验,发现前面没有空格,看来这个在不同的系统下不同。
那位能分析一下
  A=";;;;aaa"
  IFS=;
  IFS=";"; echo $A  <---------
  IFS=;
  IFS=";" echo $A    <--------- 少一个分号
两者的结果为什么不同,第一个是
    aaa  (前面4个空格)
第二个是
;;;;aaa

这两句从进程的角度在执行时有什么不同??我不知道。

论坛徽章:
0
12 [报告]
发表于 2005-03-18 02:35 |只看该作者

关于IFS的疑问

原帖由 "li2002" 发表:
看了aerofox说明觉得有些道理,感谢!!


aerofox 说对了。

原帖由 "li2002" 发表:

不过我把这个拿到sco unix(/bin/sh)下做试验,发现前面没有空格,看来这个在不同的系统下不同。


这是纯 sh (不是 bash, ksh 的 sh 兼容模式)  与 bash/ksh/zsh 的不同引起的。  请看 BASH FAQ 中的一段:

Implementation differences:
       
        bash splits only the results of expansions on IFS, using
        POSIX.2 field splitting rules; sh splits all words on IFS

例如: sh 下

A=";;;;aaaa"

echo $A

分解为

echo ""  ""  ""  ""  aaaa  (其中 ""  为空字符, 并不作为参数)

相当于

echo                  aaaa

相当于

echo aaaa

因此结果就是前面没有空格的 aaaa 了.

同理, 如果

# a=";;;;;;a;;;;;;;;;b;;;;;;;;;;;;;;;;;;;;;c;;;;;;;;;;;;;;;;;;"
# echo $a
a b c

原帖由 "li2002" 发表:

那位能分析一下
A=";;;;aaa"
IFS=;
IFS=";"; echo $A  <---------
IFS=;
IFS=";" echo $A    <--------- 少一个分号
两者的结果为什么不同,第一个是
   aaa  (前面4个空格)
第二个是
;;;;aaa

这两句从进程的角度在执行时有什么不同??我不知道。


  aaa  (前面4个空格)  -- 这个结果 aerofox  已说明了.

按说  IFS=";" echo $A  也应得到上面的结果.
如果在 N 年前,  二者的确是相同的.

但由于 IFS 经常 被 hecker 用 形如  IFS=/; export IFS
的语句在 heck program 中,   对系统的安全是个隐患. 因此现在版本的 ksh, bash  都不允许 export  IFS.  (很容易验证).
IFS=";" echo $A  中的 IFS=";" 实际也是不起作用的.

因此 IFS=";" echo $A  就是和  echo $A  一样的效果.

论坛徽章:
0
13 [报告]
发表于 2005-03-18 09:25 |只看该作者

关于IFS的疑问

lightspeed真是高手,解释得非常清楚,把我得疑问解除了,感谢!

我还有一个由上面引出来得问题想请教版主,不要嫌我烦啊。

一个shell文件1.sh,内容是
echo $A

在命令中执行(bash)
测试1:
$ A="aaa"
$ A="bbb"  ./1.sh
$ echo $A
显示:
bbb
aaa

在A="bbb"  ./1.sh中定义的A相当与在fork子进程中定义的局部变量,等同与把A="bbb" 写入1.sh的第一行中。

测试2:
$ A="aaa"
$ A="bbb"  . ./1.sh
$ echo $A
显示:
bbb
aaa

按我的想法,1.sh执行在本进程中执行,其中的A在被改变后就一直有效,所有在第二行就应该显示"bbb"了。但结果仍显示原来的值,这应该是bash从安全性上的考虑吗??说明1.sh在执行时并没有覆盖原来的A,而是用了另外的内存空间。
把此例拿到sco unix(sh)下执行时第二行的显示就是bbb,覆盖了原来的A,这好像证明了版主的意见:bash安全性提高了。

这其实还不是我原来想要问的。再看测试3
$ A="aaa"
$ A="bbb"  echo $A
$ echo $A
显示:
aaa
aaa
就是我把1.sh的内容执行放在命令行上。结果显示的却是原来的值"aaa",我想不通了,在执行此句时不应该也执行1.sh一样吗,我想问执行这一句不也是先fork再执行的吗?看意思它好像是:
1)先定义局部变量A(值是bbb)
2)fork进程,由于原环境中有A变量,所有就覆盖了定义第一步定义的局部变量A  《----但我原来的A并没有export,为什么要理它呢??
3)显示结果aaa

我想问的重点是:
A="bbb" echo $A
执行时是先赋值A,再fork进程,还是先fork进程,再定义A??
把echo $A直接写在命令行上与写在脚本中再执行脚本有什么不同???

论坛徽章:
0
14 [报告]
发表于 2005-03-18 11:00 |只看该作者

关于IFS的疑问

原帖由 "li2002" 发表:

这其实还不是我原来想要问的。再看测试3
$ A="aaa"
$ A="bbb"  echo $A
$ echo $A
显示:
aaa
aaa
就是我把1.sh的内容执行放在命令行上。结果显示的却是原来的值"aaa",我想不通了,在执行此句时不应该也执行1.sh一样吗,我想问执行这一句不也是先fork再执行的吗?看意思它好像是:
1)先定义局部变量A(值是bbb)
2)fork进程,由于原环境中有A变量,所有就覆盖了定义第一步定义的局部变量A  《----但我原来的A并没有export,为什么要理它呢??
3)显示结果aaa

我想问的重点是:
A="bbb" echo $A
执行时是先赋值A,再fork进程,还是先fork进程,再定义A??
把echo $A直接写在命令行上与写在脚本中再执行脚本有什么不同???


解释的不对。

A="bbb" echo $A

$A 是在本 shell 中扩展的。  这句等同于

A="bbb" echo aaa

A="bbb"  是将 echo 命令所处环境变量 A 设为 bbb,  
但 echo 并不用此变量,  而是用 $1 就是 aaa.

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
15 [报告]
发表于 2005-03-18 12:51 |只看该作者

关于IFS的疑问

對, 別忘了"替換 & 重組"這個特性.
在 CR 之前, command line 已被重組為:
A="bbb" echo aaa

不妨來比較一下:
  1. [netman@www tmp]$ A=aaa
  2. [netman@www tmp]$ A="bbb" echo $A
  3. aaa
  4. [netman@www tmp]$ A=aaa
  5. [netman@www tmp]$ A="bbb"; echo $A
  6. bbb
  7. [netman@www tmp]$ A=aaa
  8. [netman@www tmp]$ A="bbb" eval echo \$A
  9. bbb
复制代码


p.s. 感謝 lightspeed & aerofox 兄的解說! 受益非淺!  ^_^

论坛徽章:
0
16 [报告]
发表于 2005-03-18 14:35 |只看该作者

关于IFS的疑问

知道了,我把最基本的原则忘了,汗啊。。。。。

论坛徽章:
0
17 [报告]
发表于 2005-08-10 17:07 |只看该作者

关于IFS的疑问

name=value command 其name=value只有command會參考(而且只這次會參考).

所以下面的例子才會如此:
$ A="aaa"
$ A="bbb"  . ./1.sh
$ echo $A
显示:
bbb
aaa

而$ A="bbb"  ./1.sh應該也是一樣的情形,只是差在有沒有sub shell中執行而己.



初到貴寶地,請多指教!  f^^

论坛徽章:
0
18 [报告]
发表于 2005-08-10 19:41 |只看该作者

关于IFS的疑问

WA,一群牛人!!学习~~~~~~~~~~~~~~~~

论坛徽章:
0
19 [报告]
发表于 2005-08-10 20:48 |只看该作者

关于IFS的疑问

原帖由 "lightspeed" 发表:

1.  IFS 空白在输入的开始和结束处忽略。
2.  输入中每个非 IFS 空白的 IFS 字符,以及任何相邻的 IFS 空白,定界一个字段。
3. 非零长度 IFS 空格对字段进行定界。

原帖由 "lightspeed" 发表:

1. IFS 只对参数扩展有作用, $* 是 $1 - $n, 不包括 $0

2. IFS 对参数位置无作用. 参数位置由空白字符及有无" " 决定

所以不可能出现你想象的情况.


不好意思,lightspeed兄,是否能再將上述的二段內容再做解釋,在下實在很想了解其中的義意.

另外bash在解析shell prompt與<CR>字符之間的內容時,是不是不參考IFS變量?但若其中有做變量替換時則會?因為在下的測試結果如下:

  1. $ IFS=I
  2. $ cdI/etc
  3. -bash: cdI/etc: No such file or directory
复制代码

I仍然不是IFS所以不能區分出command name(cd)及argument(/etc)


  1. $ IFS=i
  2. $ var="one tw three four five six seven"
  3. $ for n in $var eight nine;do echo \["$n"\];done
  4. [one tw three four f]
  5. [ve s]
  6. [x seven]
  7. [eight]
  8. [nine]
复制代码

該例在做$var變量替換時,參考了IFS變量,以i區分出[one tw three four f]、[ve s]及[x seven]三個位置參數,但eight及nine仍不為所動.

說不定我若參透上面那二段話的意思,答案就出來了!  f^^

论坛徽章:
0
20 [报告]
发表于 2005-08-12 17:17 |只看该作者

关于IFS的疑问

自問自答!我想我都清楚了!

shell由stdin收進來的command line做解析,拆成字段.這一步是由一組固定的中介字符來區隔出不同的字段(其中包含white space).

接著進行後續的處理,其中包含了變數替換這一步,在這時會參考IFS變數來區分出其它的字段.

一切的解答都在O'Reilly bash 第七章呀!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP