Chinaunix

标题: 关于shell的IFS [打印本页]

作者: thinshootout    时间: 2009-03-14 11:07
标题: 关于shell的IFS
在阅读《shell十三问》时,遇到如下问题:

    #! /bin/sh
    A=B  echo  $A
    echo  $A

请问输出是什么?为什么?谢谢~
作者: HH106    时间: 2009-03-14 11:11
亲自试下不就知道了?
作者: thinshootout    时间: 2009-03-14 11:16
原帖由 HH106 于 2009-3-14 11:11 发表
亲自试下不就知道了?


我试过了,关键是:为什么~~~
作者: oldoger    时间: 2009-03-14 11:19
输出是空值。
因为A=B赋值无效。
作者: lululau    时间: 2009-03-14 11:25
A=B是传给子进程的一个环境,这个赋值对于当前进程是无效的
首先这个你用A=B command $A这种形式
在产生子进程之前,$A就被代换了,代换成了空值
再者,echo是shell的内建命令,不产生子进程
作者: thinshootout    时间: 2009-03-14 11:35
原帖由 lululau 于 2009-3-14 11:25 发表
A=B是传给子进程的一个环境,这个赋值对于当前进程是无效的
首先这个你用A=B command $A这种形式
在产生子进程之前,$A就被代换了,代换成了空值
再者,echo是shell的内建命令,不产生子进程


晓得了,多谢~~~
作者: blackold    时间: 2009-03-14 11:37
标题: 回复 #5 lululau 的帖子
如何在"子进程"中获得A的值呢?
作者: oldoger    时间: 2009-03-14 11:42
标题: 回复 #5 lululau 的帖子
有点高深,没看懂后面这句
echo是shell的内建命令,不产生子进程
看来这个“进程”问题还得好好研究一下。
作者: blackold    时间: 2009-03-14 11:45
标题: 回复 #8 oldoger 的帖子
嗯。

参考前几天的贴子,曾讨论过这个问题。

[ 本帖最后由 blackold 于 2009-3-14 11:48 编辑 ]
作者: wendaozhe    时间: 2009-03-14 11:51
原帖由 oldoger 于 2009-3-14 11:42 发表
有点高深,没看懂后面这句
echo是shell的内建命令,不产生子进程
看来这个“进程”问题还得好好研究一下。

这个地方我也有点糊涂。
请黑哥明解!
作者: blackold    时间: 2009-03-14 12:08
A=B echo $A中的$A展开在A=B赋值之前

A=B只影响当前命令的执行环境。所以第二个命令echo $A……
作者: ywlscpl    时间: 2009-03-14 12:52
标题: 回复 #11 blackold 的帖子
黑哥,有一点不理解,请指教
a=b echo是不是等价于(a=b;echo),a=b相当于在子shell中运行的,未影响到父shell的变量a
作者: linuxboy823    时间: 2009-03-14 12:55
原帖由 thinshootout 于 2009-3-14 11:07 发表
在阅读《shell十三问》时,遇到如下问题:

    #! /bin/sh
    A=B  echo  $A
    echo  $A

请问输出是什么?为什么?谢谢~



  #! /bin/sh
    A=B  echo  $A   #这行中间没有分号,应该会报错,我没有测试,呵呵!
    echo  $A
作者: ywlscpl    时间: 2009-03-14 13:06
我的理解
A=B  echo  $A  ($A先被替换成空,因为变量A为空)
==>先执行A=B,再执行echo

echo $A,则是空

不明白的就是A=B为什么变成在子shell中执行了,所以echo $A为空
作者: lululau    时间: 2009-03-14 13:09
都说了"VAR=value comman"这样的形式是将VAR作为一个环境变量传给子进程
ABS上面说的
作者: wendaozhe    时间: 2009-03-14 13:32
原帖由 ywlscpl 于 2009-3-14 13:06 发表
我的理解
A=B  echo  $A  ($A先被替换成空,因为变量A为空)
==>先执行A=B,再执行echo

echo $A,则是空

不明白的就是A=B为什么变成在子shell中执行了,所以echo $A为空

同样疑问。
作者: blackold    时间: 2009-03-14 14:27
原帖由 ywlscpl 于 2009-3-14 12:52 发表
黑哥,有一点不理解,请指教
a=b echo是不是等价于(a=b;echo),a=b相当于在子shell中运行的,未影响到父shell的变量a

不等价。
作者: blackold    时间: 2009-03-14 14:29
标题: 回复 #12 ywlscpl 的帖子
没有subshell。

bash man里面说得很清楚。

bash先标记命令行中命令名前的变量赋值,然后对后面的参数进行展开。A=B echo $A中的变量赋值只影响当前命令的执行环境,不影响当前shell的环境。

[ 本帖最后由 blackold 于 2009-3-14 14:39 编辑 ]
作者: nhw_cs    时间: 2009-03-14 14:44
a=b 与 echo 都是shell的内部功能, 也就是由shell本身实现的, 当然不产生所谓的子进程. 只有command 是外部应用程序时当前shell才产生子进程来执行command ( fork + exec )
作者: ywlscpl    时间: 2009-03-14 14:54
谢谢指教,自己再学习学习
作者: wendaozhe    时间: 2009-03-14 15:27
标题: 回复 #18 blackold 的帖子
恕我直言,我还是不太明白,小弟愚钝,还没弄清shell执行的过程,哪位明白了,请指教,真心谢谢!
作者: wendaozhe    时间: 2009-03-14 15:41
我一直的理解是:当在命令行运行./test(假设lz的脚本的名字),当前shell便产生一个subshell的子进程用以执行脚本,当subshell遇上"A=B  echo  $A"时,(由于都是内建命令,故不产生子进程)奉行先替换后重组的”原则“,先把$A替换(也就是什么都没有!),然后执A=B echo ,执行完这句A=B ,然后subshell依次执行下面的语句,echo $A,此时$A就应当是B了。请大家指正,本人真心求教!
作者: oldoger    时间: 2009-03-14 15:41
标题: 回复 #21 wendaozhe 的帖子
我也没完全明白,看来还得看看书。
作者: ywlscpl    时间: 2009-03-14 15:45
原帖由 wendaozhe 于 2009-3-14 15:41 发表
我一直的理解是:当在命令行运行./test(假设lz的脚本的名字),当前shell便产生一个subshell的子进程用以执行脚本,当subshell遇上"A=B  echo  $A"时,(由于都是内建命令,故不产生子进程)奉行先替换后重组的” ...


你的理解有个地方是肯定错了,命令是先替换后重组的,"A=B  echo  $A",$A已经被替换为空了,那命令就变成"A=B echo",怎么还可能执行echo B呢
比如a="xxx"
echo $a   ($a被替换为xxx)==>echo xxx

[ 本帖最后由 ywlscpl 于 2009-3-14 16:08 编辑 ]
作者: 山野村夫    时间: 2009-03-14 15:52
原帖由 thinshootout 于 2009-3-14 11:07 发表
在阅读《shell十三问》时,遇到如下问题:

    #! /bin/sh
    A=B  echo  $A
    echo  $A

请问输出是什么?为什么?谢谢~

应该是执行顺序的问题吧
作者: wendaozhe    时间: 2009-03-14 15:57
标题: 回复 #24 ywlscpl 的帖子
没有错啊,先替换后重组,正因为$A unset,才是 A=B echo 嘛,如果A=123那就是 A=B echo 123了。
作者: wendaozhe    时间: 2009-03-14 15:59
标题: 回复 #25 山野村夫 的帖子
关键是最后一个echo $A,可能还是对shell的执行流程不太懂,糊里糊涂的。
作者: oldoger    时间: 2009-03-14 16:08
标题: 回复 #27 wendaozhe 的帖子
所以还得好好学习,看看书
作者: ywlscpl    时间: 2009-03-14 16:09
命令替换A=B echo $A==>A=B echo
既然替换已经完成了,命令中就不会再有echo $A了

[ 本帖最后由 ywlscpl 于 2009-3-14 16:20 编辑 ]
作者: wendaozhe    时间: 2009-03-14 16:18
标题: 回复 #29 ywlscpl 的帖子
没有啊,替换之后不就是 A=B echo吗,它直接就交由subshell执行了!怎么取两次值呢?
作者: ywlscpl    时间: 2009-03-14 16:20
标题: 回复 #30 wendaozhe 的帖子
我刚才说的也不对,编辑了一下
作者: wendaozhe    时间: 2009-03-14 16:29
标题: 回复 #29 ywlscpl 的帖子
肯定不会有了因为echo $A变成了echo ,$A被替换成了null了!
作者: ywlscpl    时间: 2009-03-14 16:47
原帖由 wendaozhe 于 2009-3-14 16:29 发表
肯定不会有了因为echo $A变成了echo ,$A被替换成了null了!


对啊,可你前面说的,我也不明白你的意思了

奉行先替换后重组的”原则“,先把$A替换(也就是什么都没有!),然后执A=B echo ,执行完这句A=B ,然后subshell依次执行下面的语句,echo $A,此时$A就应当是B了

作者: ywlscpl    时间: 2009-03-14 16:49
明白了,我讨论的是A=B echo $A

你说的是 A=B echo $A
             echo $A
作者: wendaozhe    时间: 2009-03-14 16:50
标题: 回复 #33 ywlscpl 的帖子
呵呵,要知道lz的script里有两个echo $A!
作者: ywlscpl    时间: 2009-03-14 16:54
你的疑问就是A=B echo $A这条语句中的A=B为什么没影响到当前shell,这个也是我一开始的疑问。

15楼的lululau解释
都说了"VAR=value comman"这样的形式是将VAR作为一个环境变量传给子进程
ABS上面说的

黑哥解释也是一个意思
bash man里面说得很清楚。

bash先标记命令行中命令名前的变量赋值,然后对后面的参数进行展开。A=B echo $A中的变量赋值只影响当前命令的执行环境,不影响当前shell的环境。

作者: justlooks    时间: 2009-03-14 17:04
这个是关于命令行处理流程的问题吧
整个就1个命令 再处理上$先被shell替换掉,到最后的一步执行整条命令
替换在赋值执行之前

对第2个echo为什么为空我也很不解
为什么 加上 echo $A后 A=B变成只影响当前命令环境不会影响shell环境了呢??
作者: wendaozhe    时间: 2009-03-14 17:06
因为在subshell中并没有产生新的进程,如果要我强行理解的话,那就是:var=value command这种形式只把变量给子进程,自己都不用!
作者: oldoger    时间: 2009-03-14 17:14
这个先收藏了先。。
现在的情况是知道了,但没有理解原理。为何这样。
作者: blackold    时间: 2009-03-14 17:17
黑哥解释也是一个意思




首先,我说的和lululau的不同:没有子进程!

不是解析清楚了吗?

注意看贴啊。

再解析一遍:
A=B echo $A:
       bash先标记赋值"A=B",再展开$A(此时A为空),  所以没有输出。
       另外,A=B command 中的赋值只用于执行当前命令,在此即echo, 不影响当前shell环境。所以命令结束后,再执行echo $A(第二条命令)时,也没有输出"B"。
作者: blackold    时间: 2009-03-14 17:20
原帖由 wendaozhe 于 2009-3-14 17:06 发表
因为在subshell中并没有产生新的进程,如果要我强行理解的话,那就是:var=value command这种形式只把变量给子进程,自己都不用!


命令comand是可以使用var=value的,而且这也是var=value的目的,我们常用的LC_ALL=C command,就是让command在一个LC_ALL=C的环境中执行,而不是使用当前locale.
作者: wendaozhe    时间: 2009-03-14 17:23
标题: 回复 #41 blackold 的帖子
如果是这样的话,那我就理解了!
不是我原先的理解有问题,只是对var=value commond这种“特殊”的形式不了解而已!

[ 本帖最后由 wendaozhe 于 2009-3-14 17:24 编辑 ]
作者: blackold    时间: 2009-03-14 17:34
标题: 回复 #42 wendaozhe 的帖子
如果还不理解,就理解为临时变量吧,或者"局部变量"。
作者: oldoger    时间: 2009-03-14 18:12
标题: 回复 #41 blackold 的帖子
现在有点明白过来了,谢谢黑哥。
作者: xin2v    时间: 2009-03-14 19:28
root@devserver02 # ./test

B
root@devserver02 # cat test
#! /bin/sh
A=B  echo  $A
echo  $A

root@devserver02 #


为什么我的是输出的???????????????????
我用的是
root@devserver02 # cat /etc/release
                       Solaris 10 6/06 s10s_u2wos_09a SPARC
           Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
                        Use is subject to license terms.
                             Assembled 09 June 2006
作者: blackold    时间: 2009-03-14 19:37
标题: 回复 #45 xin2v 的帖子
你用的不是bash吧。
作者: xin2v    时间: 2009-03-14 19:39
奇怪奥  换了linux的版本  就和楼主说的一样啦 嘿嘿  怪啊  哈哈
[root@localhost ~]# a=b echo $a

[root@localhost ~]# echo $a

[root@localhost ~]#
作者: xin2v    时间: 2009-03-14 19:51
原帖由 blackold 于 2009-3-14 19:37 发表
你用的不是bash吧。

我用的是标准shell嘿嘿
刚明白  就是solaris自己带的shell  谢谢 黑哥
作者: haimming    时间: 2009-03-14 20:12
原帖由 blackold 于 2009-3-14 12:08 发表
A=B echo $A中的$A展开在A=B赋值之前

A=B只影响当前命令的执行环境。所以第二个命令echo $A……


我的理解,不要问为什么,这是规则如此而已
作者: linuxboy823    时间: 2009-03-14 23:57
原帖由 lululau 于 2009-3-14 13:09 发表
都说了"VAR=value comman"这样的形式是将VAR作为一个环境变量传给子进程
ABS上面说的



有空我来看下!
作者: 76862157    时间: 2009-03-15 08:47
学习了。
作者: sdzzzxj    时间: 2009-03-16 08:37
还是有些不明白,看来还是要好好的看书了
作者: 小小磊    时间: 2009-03-16 10:20
原帖由 blackold 于 2009-3-14 17:20 发表


命令comand是可以使用var=value的,而且这也是var=value的目的,我们常用的LC_ALL=C command,就是让command在一个LC_ALL=C的环境中执行,而不是使用当前locale.



这样的话,我能理解点了
作者: lj870128    时间: 2009-03-16 12:51
原帖由 lululau 于 2009-3-14 11:25 发表
A=B是传给子进程的一个环境,这个赋值对于当前进程是无效的
首先这个你用A=B command $A这种形式
在产生子进程之前,$A就被代换了,代换成了空值
再者,echo是shell的内建命令,不产生子进程

貌似有点懂了,这个应该是与bash的解释运行的顺序相关~~~
作者: nighteblis    时间: 2009-03-16 13:58
局部变量似乎还容易相通点,

不过说回来了, 你 A=B command , 这时候的command的环境变量 到底是只有 A 这个变量还是在之前的所有环境变量加上A这个变量。

如果是后者,不是也可以这样么。

A=B
command (run in A=B)
unset A

这样可以么?
作者: tianlijian    时间: 2009-03-16 14:53
原帖由 nhw_cs 于 2009-3-14 14:44 发表
a=b 与 echo 都是shell的内部功能, 也就是由shell本身实现的, 当然不产生所谓的子进程. 只有command 是外部应用程序时当前shell才产生子进程来执行command ( fork + exec )

  1. ip="192.168.0.1" ping $ip
  2. Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
  3.             [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
  4.             [-M mtu discovery hint] [-S sndbuf]
  5.             [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination
复制代码

ping 命令会产生子进程吗?如果产生,这个输出结果怎么解释?谢谢了。
作者: youshuang    时间: 2009-03-16 15:12
标题: 回复 #1 thinshootout 的帖子
试试下面这句话,如果没有分号隔开的话,bash对参数的解释是从右到左的,这点和C语言一样
echo $a a = 1
所以楼主的结果是可以理解的
作者: youshuang    时间: 2009-03-16 15:18
标题: 回复 #57 youshuang 的帖子
关于子进程,是这么回事:
我们的shell(默认BASH)是所谓解释器,当你输入一个命令执行的时候,它通过fork命令创建一个子进程,然后用exec命令把你的命令替换掉这个子进程。这个时候就有两个进程,一个是shell,一个是你的命令。通常主进程shell会通过wait函数等待你的子进程执行完毕,因此一般情况下你的shell提示符会在你的命令运行完毕之后才出现。但是也可以用&使得你的命令在后台运行,这时候shell提示符立即跳出来,这是因为shell没有调用wait函数。
作者: youshuang    时间: 2009-03-16 15:25
标题: 回复 #57 youshuang 的帖子
晕死,不好意思,说错了
作者: rhlei    时间: 2009-03-16 15:26
原帖由 youshuang 于 2009-3-16 15:18 发表
关于子进程,是这么回事:
我们的shell(默认BASH)是所谓解释器,当你输入一个命令执行的时候,它通过fork命令创建一个子进程,然后用exec命令把你的命令替换掉这个子进程。这个时候就有两个进程,一个是shell, ...


这个理解是正确的,shell本身不存在父子进程的问题。

BTW:这个问题貌似没有必要太深究吧,除非你已经炉火纯青了。不然语言的细节是很多的。
作者: tianlijian    时间: 2009-03-16 18:33
原帖由 blackold 于 2009-3-14 14:29 发表


bash先标记命令行中命令名前的变量赋值,然后对后面的参数进行展开。A=B echo $A中的变量赋值只影响当前命令的执行环境,不影响当前shell的环境。

这个在man的具体哪一块有说明?在abs哪一声有说明?
作者: blackold    时间: 2009-03-16 18:45
标题: 回复 #61 tianlijian 的帖子
man中命令的执行过程。
ABS没看。
作者: wtuter    时间: 2009-03-16 18:54
[root@]# export A=B  echo  $A
[root@]# A=B  echo  $A
B




[root@]# export A=B  echo  $A
[root@]# echo  $A
B

[ 本帖最后由 wtuter 于 2009-3-16 18:55 编辑 ]
作者: tianlijian    时间: 2009-03-16 19:22
原帖由 wtuter 于 2009-3-16 18:54 发表
[root@]# export A=B  echo  $A
[root@]# A=B  echo  $A
B




[root@]# export A=B  echo  $A
[root@]# echo  $A
B

export a=b echo $a中的echo $a没有当命令来执行,太有想象力了,哈哈。
作者: labrador001    时间: 2009-03-16 20:10
#! /bin/sh

a=b echo $a
echo $a
echo ${a=123}

我想上面的代码可以说明问题。 ${a=123} 可以参加shell13问中:${file=my.file.txt} :若 $file 沒設定,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt 。 (空值及非空值時不作處理)
我的理解是:
a=b echo $a  这一句给a赋值并没有成功,并且在这个赋值中将 echo  $a 解析成了命令,因为a没有赋值成功,所以$a是没有设定的,因此第一句和第二句 echo出来是空。而第三句,就是用来检验$a是否是没有设定。

至于为什么 a=b echo $a 没有赋值成功。见 " "(雙引號) 與 ' '(單引號)差在哪? 这一章
        $ A=B C        # 空白鍵未被關掉,作為 IFS 處理。
        $ C: command not found.
              $ echo $A

解释了。这里的C就是楼主的 echo $a

呵呵,个人浅见,请大家指正。

[ 本帖最后由 labrador001 于 2009-3-16 20:26 编辑 ]
作者: blackold    时间: 2009-03-16 20:53
看不懂了。
作者: locale    时间: 2009-03-17 10:12
继续看不懂,很感兴趣,继续看大家讨论
作者: locale    时间: 2009-03-17 10:44
[root@localhost:/test]# cat 33
#!/bin/bash
#name = 33
A=B echo $$
echo $$
[root@localhost:/test]# ./33
2200
2200
[root@localhost:/test]# echo $$
2078
这个能不能说明,这个脚本里面在A=B echo $A没有用到子进程,因为echo$$和下一行的echo $$显示的是一样的进程号。抛一个
作者: MingLin1231    时间: 2009-03-17 19:11
65楼朋友的说法才是正解。
A=B echo $A 其实前面A=B 什么也没做,因为它根本不是一个独立语句。BASH里面是以回车或分号来进行语句区分的,空格只是IFS,你在中间加一个分号再执行就清楚了。
A=B;echo $A
作者: MingLin1231    时间: 2009-03-17 19:18
汗,突然发现自己的理解并不正确。。。
作者: lastexile    时间: 2009-03-20 11:03
看起来好像不是一般高深
作者: 我是DBA    时间: 2009-03-20 11:15
本来以为是懂的,看来才知道不懂。
作者: dayan_he    时间: 2009-03-21 23:04
原帖由 我是DBA 于 2009-3-20 11:15 发表
本来以为是懂的,看来才知道不懂。



试一下这个


$a=b sh
sh$echo  $a         
sh$exit
$echo $a

[ 本帖最后由 dayan_he 于 2009-3-21 23:08 编辑 ]
作者: pepe    时间: 2009-03-23 16:01
赞成65楼的解释
作者: blackold    时间: 2009-03-23 16:14
why?
$ echo a:
::

$ a=foo eval echo \$a
foo

$ echo a:
::

作者: dayan_he    时间: 2009-03-23 17:28
标题: 回复 #74 pepe 的帖子
说明你没搞懂
作者: 網中人    时间: 2009-03-24 10:10
原帖由 labrador001 于 2009-3-16 20:10 发表
#! /bin/sh

a=b echo $a
echo $a
echo ${a=123}

我想上面的代码可以说明问题。 ${a=123} 可以参加shell13问中:${file=my.file.txt} :若 $file 沒設定,則使用 my.file.txt 作傳回值,同時將 $file 賦 ...


good job!
總算有人看得懂了。

不過,要細說的話,要扯上 shell 在 interpret 一個 command line 時的 priority 。
基本上,其順序如下:
1,將 line 拆成 words (IFS很重要)
2,括展 alias
3,擴展 { }
4,擴展 ~
5,擴展 $variable, $(command), `command`
6,重組再拆成 words
7,括展 wildcards
8,處理 I/O redirection
9,載入命令運行
如果大家有O'Reilly英文版的 Learning the Bash(2nd)的話,請多端詳p178的圖(細節略異)

回到LZ的問題,看上面 5 跟 6 的順序然後才是 9 。
也就是在 6 重組命令時 $A 已經完成替換,當時的 environment 是沒賦值,
因此重組後就是 A=B echo
然後在第 9 的步驟運行命令時, A=B 是給 echo 命令的 local environment,
不管是否 built-in command,都不影響當前的 shell (不同的 shell 在實作上或有差異)
所以第二行的 echo $A 也是得到沒賦值

[ 本帖最后由 網中人 于 2009-3-24 10:56 编辑 ]
作者: 網中人    时间: 2009-03-24 10:12
原帖由 blackold 于 2009-3-23 16:14 发表
why?

因為你用了 eval ^_^
作者: blackold    时间: 2009-03-24 10:18
标题: 回复 #78 網中人 的帖子
拜托,我不是对我自己命令问why.

1,將 line 拆成 words (IFS很重要)

这个不使用IFS吧。

[ 本帖最后由 blackold 于 2009-3-24 10:20 编辑 ]
作者: 我是DBA    时间: 2009-03-24 10:24
标题: 回复 #77 網中人 的帖子
这个解释很明白,谢谢
作者: 網中人    时间: 2009-03-24 10:27
原帖由 blackold 于 2009-3-24 10:18 发表
拜托,我不是对我自己命令问why.


这个不使用IFS吧。


願問其詳。
作者: blackold    时间: 2009-03-24 10:31
我通过eval说明赋值是成功的,而不是65楼所说的赋值不成功。

第一步使用 metacharacter,与IFS没有关系。

[ 本帖最后由 blackold 于 2009-3-24 10:56 编辑 ]
作者: 網中人    时间: 2009-03-24 10:48
原帖由 blackold 于 2009-3-24 10:31 发表
我通过eval说明赋是成功的,而不是65所说的赋值不成功。

第一步使用 metacharacter,与IFS没有关系。



還是看不懂...  >_<

eval 沒那麼難理解,簡單來說就是“多層重組”(記得我在13問後面的補充討論中有提到)
也就是第一次重組完成,運行再重組一次。
kenny@x60:~> a=b eval echo \$a
b
kenny@x60:~> echo $a

看第二次的 echo $a 依然沒賦值,你怎反駁 65 樓的說法呢?

運用 eval 那行簡單看成 a=b 是傳給 eval 的就好,而不是傳給 echo 的。
因為 eval 已經獲的 a=b 的值了,因此當 eval 再重組 echo $a 的時候就得到 echo b。
(echo \$a 在第一次 shell 重組已經變成 echo $a 了)


又,
我說的是拆成 word ,看不懂你為何要扯 metacharacter,能否說明白?
消除了誤會討論起來才有交集。
作者: blackold    时间: 2009-03-24 11:00
标题: 回复 #83 網中人 的帖子
sorry,刚才漏写了两个字。

将line拆成words( split into tokens)不是根据metacharacter吗?
作者: ywlscpl    时间: 2009-03-24 11:06
现在的理解是
a=b echo $a
1、$a先被替换为空:a=b echo
2、空格作为IFS处理:a=b;echo
3、结果:输出一个空行
4、当前shell环境中$a的值为空,a=b并未影响到当前shell环境,这个是bash定义var=str command这种特殊格式命令的结果
作者: 網中人    时间: 2009-03-24 11:06
原帖由 blackold 于 2009-3-24 11:00 发表
sorry,刚才漏写了两个字。

将line拆成words( split into tokens)不是根据metacharacter吗?



哦,那我理解您的意思了。

不是的,IFS 的 F 就是 field 的意思。
在英文上,將 field 翻譯成中文,應該是欗位的意思。
不過大家對這個不好理解,所以很多人也就用 word (詞)來代替 field 來說明。如此好理解多了。

Internal Field Separate 就是欗位的分隔符號,也可以理解為 word 的分隔符號。

要是換成用 token ,那更是不好理解。
因此,在討論的時候,如果大家都理解得來的英文術語,我一般都不作翻譯。
怕是翻譯過來反而大家誤會了。
作者: 網中人    时间: 2009-03-24 11:09
原帖由 ywlscpl 于 2009-3-24 11:06 发表
现在的理解是
a=b echo $a
1、$a先被替换为空:a=b echo
2、空格作为IFS处理:a=b;echo
3、结果:输出一个空行
4、当前shell环境中$a的值为空,a=b并未影响到当前shell环境,这个是bash定义var=str command这 ...


關於 2,
小心那個 ; 號,因為如果用了 ; 就是分成兩個 command line 來處理,也就是
a=b
echo
那跟 a=b echo 是不一樣的。小心。

關於4,
那不應該是空值,而是沒賦值。
抱歉,我剛才在回覆時也講錯了,現在已經修改過來了。
作者: blackold    时间: 2009-03-24 11:14
标题: 回复 #86 網中人 的帖子
跑题了:
The following is a brief description of the shell's operation when it
reads and executes a command.  Basically, the shell does the following:

  1. Reads its input from a file (*note Shell Scripts:, from a string
     supplied as an argument to the `-c' invocation option (*note
     Invoking Bash:, or from the user's terminal.

  2. Breaks the input into words and operators, obeying the quoting
     rules described in *Note Quoting::.  These tokens are separated by
     `metacharacters'.  Alias expansion is performed by this step
     (*note Aliases:.
`IFS'
     A list of characters that separate fields; used when the shell
     splits words as part of expansion.

作者: ywlscpl    时间: 2009-03-24 11:19
标题: 回复 #87 網中人 的帖子
谢谢前辈指教
自己说的很不严谨,第4点变量a是没赋值。
关于第2点,如何验证a=b这条语句是执行过的呢?

发现 a=b echo $a和ls echo $a不一样,前者输出一个空行(a=b是否执行过不太明确),后者其实执行的是ls echo

[ 本帖最后由 ywlscpl 于 2009-3-24 11:23 编辑 ]
作者: 網中人    时间: 2009-03-24 11:22
原帖由 blackold 于 2009-3-24 11:14 发表
跑题了:


Thanks for your info.

或許您的理解是對的,只是我對 metacharacter 的定義誤會了。

在我看來,$, space, \, ;, >, *, ... 都是 meta
如果用來做 token 切割,那下面這行:
a=b echo $a 就分成兩個 tokens:
a=b echo
a
然後我就解析不來後面的 expansions 了... >_<

但如果是用 IFS 來切割,就變成三個 tokens:
a=b
echo
$a
如此,$a 就是 variable expansion,而這個時候因為 a 還沒賦值,所以替換不出任何東西。
再重組,就成為:
a=b echo
如此,我還勉強理解也解析得來...
作者: 網中人    时间: 2009-03-24 11:24
原帖由 ywlscpl 于 2009-3-24 11:19 发表
谢谢前辈指教
自己说的很不严谨,第4点变量a是没赋值。
关于第2点,如何验证a=b这条语句是执行过的呢?

发现 a=b echo $a和ls echo $a不一样,前者输出一个空行(a=b是否执行过不太明确),后者其实执行的是 ...


哈,你說的 a=b echo $a 不就是我們現在討論的嗎?

至於
ls echo $a
可以這樣來:
命令行被分割之後,得到
ls
echo
$a
因為 a 還沒有值,那重組後就是:
ls echo
作者: locale    时间: 2009-03-24 11:26
一群学究啊,郁闷,我这个菜鸟看半天,都忘了自己在干啥,汗,我去学问了。你们慢慢学究。
作者: blackold    时间: 2009-03-24 11:28
标题: 回复 #90 網中人 的帖子
按照bash man, bash将:
a=b echo $a
split into 3 个 tokens:
a=b
echo
$a

您的meta与bash的metacharacter不同。
作者: 網中人    时间: 2009-03-24 11:31
原帖由 blackold 于 2009-3-24 11:28 发表
按照bash man, bash将:
a=b echo $a
split into 3 个 tokens:
a=b
echo
$a

您的meta与bash的metacharacter不同。


恩,所以是有誤會之處了。

斗膽請問老哥:那您所理解的 meta 呢?
作者: blackold    时间: 2009-03-24 11:33
标题: 回复 #94 網中人 的帖子
您抬举我了,我这水平啊有什么理解,都是bash document里面说的:
`metacharacter'
     A character that, when unquoted, separates words.  A metacharacter
     is a `blank' or one of the following characters: `|', `&', `;',
     `(', `)', `<', or `>'.

作者: 網中人    时间: 2009-03-24 11:37
原帖由 blackold 于 2009-3-24 11:33 发表
您抬举我了,我这水平啊有什么理解,都是bash document里面说的:


黑哥大大謙虛了!

事實上,您為大家示範了所有學習中最正確的方法---就是 man !

這點很重要哦。
我們自己的解釋都是按各自的理解來說的,有點如盲人摸象。
真的要知道原貌,就是看 man !

或許我個人在理解 token separation 的時候還有盲點。
希望不會誤導大家就好了。
作者: blackold    时间: 2009-03-24 11:44
标题: 回复 #96 網中人 的帖子
netman, 这是实话啊。
半路出家,接触linux时间不长,经常犯错,需不断向各位前辈学习。
作者: 網中人    时间: 2009-03-24 11:55
原帖由 blackold 于 2009-3-24 11:44 发表
netman, 这是实话啊。
半路出家,接触linux时间不长,经常犯错,需不断向各位前辈学习。


嘿,俺也是半路出家。
學電腦之前我是拿鍋勺子的!

學無先後,達者為師。
大家一起加油!
作者: merlin852    时间: 2009-03-24 12:28
向两位大师学习啊
作者: luyi1983    时间: 2009-03-24 14:21
谁再来作个总结成词吧
我脑子容易搞混 搞个正确的记住 。。。>_<




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2