作者 主題: Shell script 來讀取資料並且修改 TEXT 檔案  (閱讀 15433 次)

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

krischen

  • 可愛的小學生
  • *
  • 文章數: 5
    • 檢視個人資料
各位先進 我想要讀取一個TEXT檔 的第一行 其中一個欄位作為SHELL SCRIPT處理的變數來源
但是同時也必須將第一行從原來的檔案刪除 如此原來的第二行遞補 做為下一次SCRIPT的來源
可是我想不出來要怎麼做比較方便
TEXT 檔案格式(file-list.txt):
aaa.0529.xyz
bbb.0530.abc
ccc.0531.opq

第一次SCRIPT執行時 讀取第一行 aaa.0528.xyz  摘取0528 做一些處理
但是同時也需要將 aaa.0528.xyz 從原檔案中移除 (也不要空行 否則製造下次讀取麻煩)
最主要也是因為SCRIPT 會產生一個新的檔名 append 到 file-list.txt 的最後一行
變成為(file-list.txt):
bbb.0530.abc
ccc.0531.opq
ddd.0601.rst

有先進可以指點一下使用BASH 如何做出類似SCRIP? 感謝

wenlien

  • 憂鬱的高中生
  • ***
  • 文章數: 119
  • 性別: 男
    • 檢視個人資料
    • Open or not open, that is the stupid question.
各位先進 我想要讀取一個TEXT檔 的第一行 其中一個欄位作為SHELL SCRIPT處理的變數來源
但是同時也必須將第一行從原來的檔案刪除 如此原來的第二行遞補 做為下一次SCRIPT的來源
可是我想不出來要怎麼做比較方便
TEXT 檔案格式(file-list.txt):
aaa.0529.xyz
bbb.0530.abc
ccc.0531.opq

第一次SCRIPT執行時 讀取第一行 aaa.0528.xyz  摘取0528 做一些處理
但是同時也需要將 aaa.0528.xyz 從原檔案中移除 (也不要空行 否則製造下次讀取麻煩)
最主要也是因為SCRIPT 會產生一個新的檔名 append 到 file-list.txt 的最後一行
變成為(file-list.txt):
bbb.0530.abc
ccc.0531.opq
ddd.0601.rst

有先進可以指點一下使用BASH 如何做出類似SCRIP? 感謝


我用的是暴力解法:
s=`head -1 file-list.txt`                     ## 讀取第一行, s=aaa.0529.xyz
head +2 file-list.txt > ./file-list.txt.bak ## 讀取第二行到最後一行, 並輸出到file-list.txt.bak
mv ./file-list.txt.bak ./file-list.txt         ## 將file-list.txt.bak更名為file-list.txt

regards,

Stanley Huang
regards,

Stanley Huang

krischen

  • 可愛的小學生
  • *
  • 文章數: 5
    • 檢視個人資料
感謝你的回覆與解答  雖然是"暴力法" 也是可能可以解決問題
我原先想用AWK 或 SED 來做  功力不夠所以卡在這裡
不過這其實更加簡單 又很直覺  謝謝

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17453
    • 檢視個人資料
    • http://www.study-area.org
最主要也是因為SCRIPT 會產生一個新的檔名 append 到 file-list.txt 的最後一行

請問新檔名怎麼來的?
產生的規則如何?

krischen

  • 可愛的小學生
  • *
  • 文章數: 5
    • 檢視個人資料
感謝回覆 由另一SCRIPT執行而來 因為一直想不出來要如何做
所以目前還是要人工來做 檔名是由DATE加上一些OPTIONS產生的

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17453
    • 檢視個人資料
    • http://www.study-area.org
另外的 script 產生的檔案在固定目錄嗎?
有一定規則嗎?

我先假設新檔案會產生在 src.dir 目錄內,而且新檔案以時間順序來取最新一份:
同時假設存放檔案名單的檔案為 file-list.txt

代碼: [選擇]
#!/bin/bash

l_file=file-list.txt
head=`head -1 $l_file`
tail="`tail -n +2 $l_file`"
f_dir=src.dir
new_fn=`ls -t $f_dir | head -1`

# extract number
num=`echo $head | sed 's/[^0-9]//g'`
echo $num

# restore file
echo "$tail" > $l_file
echo $new_fn >> $l_file
« 上次編輯: 2010-06-13 20:09 由 netman »

wenlien

  • 憂鬱的高中生
  • ***
  • 文章數: 119
  • 性別: 男
    • 檢視個人資料
    • Open or not open, that is the stupid question.
感謝你的回覆與解答  雖然是"暴力法" 也是可能可以解決問題
我原先想用AWK 或 SED 來做  功力不夠所以卡在這裡
不過這其實更加簡單 又很直覺  謝謝

awk, sed在做完資料修改後, 會將結果顯示到標準輸出. ( 我不知道是否有辦法可以直接修改檔案 )
所以, 我通常也是用兩段式的方法來處理.
#!/bin/bash
sLine="`head -1 ./file-list.txt`"
sed -e '1,1d' ./file-list.txt > ./file-list.txt.tmp
mv ./file-list.txt.tmp ./file-list.txt

但是這樣處理會比用tail -n +2 快嗎??

Just try it!

代碼: [選擇]
#!/bin/bash
echo "sed -e '1,1d' ./t.txt > ./t2.txt"
#echo "head -n +2 ./t.txt > ./t2.txt"
for i in seq 1 100
do
  sed -e '1,1d' ./t.txt > ./t2.txt
  #tail -n +2 ./t.txt > ./t2.txt
done

stanley@Stanley-Ubuntu:~$ time ./test.sh
head -n +2 ./t.txt > ./t2.txt

real    0m0.244s
user    0m0.016s
sys     0m0.092s


stanley@Stanley-Ubuntu:~$ time ./test.sh
sed -e '1,1d' ./t.txt > ./t2.txt

real    0m0.956s
user    0m0.716s
sys     0m0.100s


stanley@Stanley-Ubuntu:~$

如果你的server很忙碌, 或檔案很大.
這樣的做法, 其實會浪費很多資源.
所以, 如果沒有絕對的必要,
其實就把舊檔改名後讓程式去處理就好了,
這樣你就不會回寫檔案了!
代碼: [選擇]
#!/bin/bash
mv file-list.txt file-list.txt.working ## ps. 此時另一隻程式, 還是在持續寫入到file-list.txt
cat ./file-list.txt.working | read line
do
  do some thing...
done

regards,

Stanley Huang
regards,

Stanley Huang

krischen

  • 可愛的小學生
  • *
  • 文章數: 5
    • 檢視個人資料
感謝netman 和 wenlien,

原先 wenlien前輩 之前第一次回覆的head +2   因為head不接受直接正值(會被認為是檔案)
而且我忘記用tail 來測試 所以我才想請問netman前輩
現在我用tail -n +2 就可以讓我的script正常跑出我想要的結果
感謝netman前輩的提醒 也很感謝wenlien的熱心測試與sed的效率比較

我想要的結果可以用 以下達成

OLD=`head -1 file-list.txt`
tail -n +2 file-list.txt > file-list.txt-bak
mv file-list.txt-bak file-list.txt

再次感謝兩位的熱心幫助