Discussion:
[問題] shell script 變數問題
(时间太久无法回复)
阿朱哥
2014-01-22 12:03:27 UTC
Permalink
想請教一下為何下列第二和第三種方法會顯示錯誤訊息

1.
TMP1=/root/zh/pp/pg1.tmp
TMP2=/root/zh/pp/pg2.tmp

2.
q=1
while [ "$q" -le "4" ];do
TMP${q}=/root/zh/pp/pg${q}.tmp
q=`expr $q + 1`
done

3.
for q in 1 2 3 4
do
TMP$q=/root/zh/pp/pg$q.tmp
done

第二和第三錯誤訊息都是
+ TMP1=/root/zh/pp/pg.tmp
pp.sh: line 4: TMP1=/root/zh/pp/pg1.tmp: No such file or directory
+ TMP2=/root/zh/pp/pg2.tmp
pp.sh: line 4: TMP2=/root/zh/pp/pg2.tmp: No such file or directory

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.33.55.125
阿朱哥
2014-01-23 06:56:50 UTC
Permalink
※ 引述《guessi (沒)》之銘言:
: 當有變數存在時 TMP${q}=something只能被當作是一般字串 而非命令
: 你可以試著這樣操作 並檢驗它的執行過程
: echo "---- start ----"
: x=123
: foo${x}bar=foobar
: echo "${foo123bar}"
: echo "---- end ----"
: 接著執行它 (黃字為執行過程 而白字為執行輸出)
: + echo '---- start ----'
: ---- start ----
: + x=123
: + foo123bar=foobar <--- 這裡的"foobar123=foobar"被解讀為function的名稱
: line 5: foo123bar=foobar: command not found
: + echo <--- 由於前一行已經失敗 所以foo123bar只會是個不存在的變數 就報錯啦!
: + echo '---- end ----'
: ---- end ----
: 這邊你需要的是eval幫你將字串轉換為執行命令 (詳細請查man eval)
: 也就是改寫成下面這樣
: ----8<----8<----8<----8<----8<----8<----8<----8<----
: for q in 1 2 3 4; do
: eval TMP${q}="/root/zh/pp/pg${q}.tmp"
: done
: # 驗證輸出 就會是你想要的結果啦~
: echo ${TMP1} ${TMP2} ${TMP3} ${TMP4}
: ---->8---->8---->8---->8---->8---->8---->8---->8----

你好、想再請教一下
今天我輸出的時候也想利用迴圈的方式輸出
所以我寫成下面這樣

file=/root/zh/pp/file.log
for q in 1 2 3; do
eval TMP${q}="/root/zh/pp/pg${q}.tmp"
done

for j in 1 2 3; do
eval "cat $TMP$j >> $file"
done

但是實際執行時又出現問題了
+ for j in 1 2 3
+ eval 'cat 1 >> /root/zh/pp/file.log'
++ cat 1
cat: 1: No such file or directory

請問又該如何修正?

: ※ 引述《zhucc (阿朱哥)》之銘言:
: : 想請教一下為何下列第二和第三種方法會顯示錯誤訊息
: : 1.
: : TMP1=/root/zh/pp/pg1.tmp
: : TMP2=/root/zh/pp/pg2.tmp
: : 2.
: : q=1
: : while [ "$q" -le "4" ];do
: : TMP${q}=/root/zh/pp/pg${q}.tmp
: : q=`expr $q + 1`
: : done
: : 3.
: : for q in 1 2 3 4
: : do
: : TMP$q=/root/zh/pp/pg$q.tmp
: : done
: : 第二和第三錯誤訊息都是
: : + TMP1=/root/zh/pp/pg.tmp
: : pp.sh: line 4: TMP1=/root/zh/pp/pg1.tmp: No such file or directory
: : + TMP2=/root/zh/pp/pg2.tmp
: : pp.sh: line 4: TMP2=/root/zh/pp/pg2.tmp: No such file or directory

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.33.55.125
釣到一隻猴子@_@
2014-01-23 07:19:13 UTC
Permalink
※ 引述《zhucc (阿朱哥)》之銘言:
: 你好、想再請教一下
: 今天我輸出的時候也想利用迴圈的方式輸出
: 所以我寫成下面這樣
: file=/root/zh/pp/file.log
: for q in 1 2 3; do
: eval TMP${q}="/root/zh/pp/pg${q}.tmp"
: done
: for j in 1 2 3; do
: eval "cat $TMP$j >> $file"
eval "cat \$TMP$j >> $file"
: done
: 但是實際執行時又出現問題了
: + for j in 1 2 3
: + eval 'cat 1 >> /root/zh/pp/file.log'
這邊就看出最後被解析成 'cat 1 >> /root/zh/pp/file.log'
你"cat $TMP$j >> $file"進到SHELL後就會被直接解析成上面了
最主要問題是 $TMP << 這個應該要再eval裡面解析 而不是在SHELL
所以要改成 \$TMP 讓SHELL知道那$不是變數開頭 只是個$字元
: ++ cat 1
: cat: 1: No such file or directory
: 請問又該如何修正?

--
推 XXXXGAY:你聽過樹懶叫的聲音嗎? 01/05 02:28
推 HornyDragon:樓上一定聽過還敢說 01/05 02:30
推 XXXXGAY:我會樹懶叫唷,樓上想聽嗎?  01/05 02:33
→ jijiyyder:樓上和樓樓上好閃  01/05 02:34
推 ggwha:我想起龍大和貓大決鬥旳推娃  01/05 02:38
推 kongtson:看來上面兩位要生小龍貓囉  01/05 03:19

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.115.202.156
Rickie Yang
2014-01-24 18:03:46 UTC
Permalink
※ 引述《zhucc (阿朱哥)》之銘言:
: 你好、想再請教一下
: 今天我輸出的時候也想利用迴圈的方式輸出
: 所以我寫成下面這樣
: file=/root/zh/pp/file.log
: for q in 1 2 3; do
: eval TMP${q}="/root/zh/pp/pg${q}.tmp"
: done
: for j in 1 2 3; do
: eval "cat $TMP$j >> $file"
: done
: 但是實際執行時又出現問題了
: + for j in 1 2 3
: + eval 'cat 1 >> /root/zh/pp/file.log'
: ++ cat 1
: cat: 1: No such file or directory
: 請問又該如何修正?

其實 script 跟程式一樣,能簡單就不要複雜...
不知道你確切的需求是什麼,不過如果就你的例子,其實可以直接 cat
或用 bash 的 array 來作. 可讀性可能會高一些.

file=/root/zh/pp/file.log
for q in 1 2 3
do
cat /root/zh/pp/pg${q}.tmp >> ${file}
done

或是 bash 的 array:

file=/root/zh/pp/file.log
for q in 1 2 3; do
TMP[${q}]="/root/zh/pp/pg${q}.tmp"
done

for j in 1 2 3; do
cat ${TMP[${j}]} >> $file"
done

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 203.222.17.107

Loading...