作者 主題: Shell Script疑問  (閱讀 8365 次)

0 會員 與 1 訪客 正在閱讀本文。

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 於: 2005-12-28 14:41 »
  想問一下,在迴圈裡面的"變數"有所謂的"生命週期"嗎?也就是說在迴圈裡面的變數在迴圈run完後就就沒有了?因為小弟想了一個程式如下:但試不出來@@|||

先假設 /tmp/alluser 如下:
aa
bb
cc
dd
而/tmp/mailuser如下:
bb
cc
然後程式如下:
代碼: [選擇]
#!/bin/bash
/bin/cat /tmp/alluser | while read auser
do
i=1
 cat /tmp/mailuser | while read euser
  do
    if [ "$auser" == "$euser" ] ; then
          i=0
    fi
  done
    if [ "$i" == "1" ] ; then
    echo $auser >> /tmp/nouser
    fi
done


可是跑出來後去/tmp/nouser看是全部user都有……
然後我在if [ "$i" == "1" ] ; then這一行上面有插一個echo $i去看看i的值,發現根本i值就全是1沒變過,所以表示上層迴圈跑完後到下一個迴圈後i值就還是回到1了??
實在不了解,還煩請各位先進解惑一下!謝謝
*萬般帶不走,唯有業隨身**

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
Shell Script疑問
« 回覆 #1 於: 2005-12-28 15:34 »
改成這樣吧
代碼: [選擇]

#!/bin/bash
while read auser
do
    i=1
    while read euser
    do
        if [ "$auser" = "$euser" ] ; then
            i=0
        fi
    done < /tmp/mailuser
    if [ "$i" = "1" ] ; then
        echo $auser >> /tmp/nouser
    fi
done  < /tmp/alluser


我推論,你那 cat 及 | 是同一行指令,視同另一程式的執行,
變數會傳不出來。

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
Shell Script疑問
« 回覆 #2 於: 2005-12-28 15:41 »
按你的需求,有更方便的方法
代碼: [選擇]

cat /tmp/alluser /tmp/mailuser | sort | uniq -u > /tmp/nouser

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 回覆 #3 於: 2005-12-28 15:52 »
引述: "thyme"
  我推論,你那 cat 及 | 是同一行指令,視同另一程式的執行,
變數會傳不出來。


  實在感謝thyme先進的指導,原來還可以這樣把檔案輸入給while read 用 :D ,但我還是不太了解為什麼cat 及 | 是同一行指令,視同另一程式的執行呢?
有什麼可以參考的文章嗎?我去google用shell script搜尋,但好像很少講這個耶 :( ,煩請指導囉!  感恩 X 無限
*萬般帶不走,唯有業隨身**

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 回覆 #4 於: 2005-12-28 15:58 »
引述: "thyme"
按你的需求,有更方便的方法
代碼: [選擇]

cat /tmp/alluser /tmp/mailuser | sort | uniq -u > /tmp/nouser


確實如此,我怎麼蹺了一大圈!
*萬般帶不走,唯有業隨身**

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
Shell Script疑問
« 回覆 #5 於: 2005-12-28 16:50 »
引述: "蒼邪"
引述: "thyme"
  我推論,你那 cat 及 | 是同一行指令,視同另一程式的執行,
變數會傳不出來。


  實在感謝thyme先進的指導,原來還可以這樣把檔案輸入給while read 用 :D ,但我還是不太了解為什麼cat 及 | 是同一行指令,視同另一程式的執行呢?
有什麼可以參考的文章嗎?我去google用shell script搜尋,但好像很少講這個耶 :( ,煩請指導囉!  感恩 X 無限


我也不知哪兒可以參考,這是我花了不少時間 debug 出來的結論,
感覺加了 | 後,會新開一個shell去執行指令,既然是新開的shell,
那當然就傳不回來原程式了。
還有另一個寫法也會有這特性,那就是 (  ) 中間的指令,
裡面的變數值也傳不出來,例如
代碼: [選擇]

$ i=3;(i=1;echo $i);echo $i
1
3

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17464
    • 檢視個人資料
    • http://www.study-area.org
Shell Script疑問
« 回覆 #6 於: 2005-12-28 16:57 »
用 | 會產生出 sub shell ...
要不, 改為這樣看看:

while read line
do
......
done < file

我不確定是否可以, 有時間再 try try 看.

另外, (command...) 本來就稱為 nested subshell .

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 回覆 #7 於: 2005-12-29 10:11 »
  感謝thyme和netman的指導……我大致上了解,看來寫shell script還是有限制,對於我這種寫shell script的菜鳥來說,真是難過>_<"
因為可能只知道一種方法,如果這種方法不行…就沒輒了……
還望討論區的先進們多教導教導!感激不儘吶 :lol:
*萬般帶不走,唯有業隨身**

jou

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 4989
  • 性別: 男
    • 檢視個人資料
Shell Script疑問
« 回覆 #8 於: 2005-12-29 10:19 »
所以您可以把 子程序 所產生的結果存到暫存檔中
等一下回到 父程序 時,再叫出來用。

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 回覆 #9 於: 2005-12-29 19:55 »
引述: "jou"
所以您可以把 子程序 所產生的結果存到暫存檔中
等一下回到 父程序 時,再叫出來用。


  請問jou先進,這該怎麼做呢? :cry: 不是很懂耶……
*萬般帶不走,唯有業隨身**

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17464
    • 檢視個人資料
    • http://www.study-area.org
Shell Script疑問
« 回覆 #10 於: 2005-12-29 23:34 »
比方說:
代碼: [選擇]
kenny@x40:~/tmp> cat 1.sh
#!/bin/bash

n=1
cat 1.txt | while read line
do
        echo $line
        eval l$n=\$line
        ((n++))
done

echo ----
for ((i=1;i<=$((n-1));i++))
do
        eval echo \\\$l$i is: \$l$i
done
kenny@x40:~/tmp> ./1.sh
a
b
c
d
----
kenny@x40:~/tmp>

你會發現 --- 底下的變數是抓不出來的.

但改為:
代碼: [選擇]
kenny@x40:~/tmp> cat 1.sh
#!/bin/bash

n=1
while read line
do
        echo $line
        eval l$n=\$line
        ((n++))
done < 1.txt

echo ----
for ((i=1;i<=$((n-1));i++))
do
        eval echo \\\$l$i is: \$l$i
done
kenny@x40:~/tmp> ./1.sh
a
b
c
d
----
$l1 is: a
$l2 is: b
$l3 is: c
$l4 is: d
kenny@x40:~/tmp>

那就可以抓到了...

如果要改為存在 file 的話:
代碼: [選擇]
kenny@x40:~/tmp> cat 1.sh
#!/bin/bash

_tmp=tmp.file
n=1

cat /dev/null > $_tmp

cat 1.txt | while read line
do
        echo $line
        eval echo l$n=\$line >> $_tmp
        ((n++))
done < 1.txt

echo ----

source $_tmp
m=$(cat $_tmp | wc -l)
for ((i=1;i<=m;i++))
do
        eval echo \\\$l$i is: \$l$i
done
kenny@x40:~/tmp> ./1.sh
a
b
c
d
----
$l1 is: a
$l2 is: b
$l3 is: c
$l4 is: d
kenny@x40:~/tmp>

主要是利 source 的技巧.

以上只是範例, 具體請自己來參考了.

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 回覆 #11 於: 2005-12-30 01:21 »
引述: "netman"

        eval echo \\\$l$i is: \$l$i


  先感謝netman先進的指導了!我了解以上用法,也知道存檔用source來讀取!
額外想問一個問題,像上面我引言的的這行,查過google,eval是用來將變數替換掉再把指令執行一次,\$l$i這可以理解,但這行的\\\$l$i為什麼一定要三個\\\才能跳脫掉呢?
因為對eval不是很了解,有什麼地方可參考嗎?煩請指導,謝謝 :D
*萬般帶不走,唯有業隨身**

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17464
    • 檢視個人資料
    • http://www.study-area.org
Shell Script疑問
« 回覆 #12 於: 2005-12-30 01:30 »
\\ 可得到 \
\$ 可得到 $
\\\$ 就是 \$

蒼邪

  • 憂鬱的高中生
  • ***
  • 文章數: 199
    • 檢視個人資料
Shell Script疑問
« 回覆 #13 於: 2005-12-30 08:42 »
  了解,感激不儘!! :D
*萬般帶不走,唯有業隨身**