iT邦幫忙

0

批次檔問題

  • 分享至 

  • xImage

各位大哥、大姊好
小弟這裡有一個批次檔的問題想請教各位
今天我C槽裡有10份數據資料,我想從這10份裡面擷取某一個欄位的值(所以擷取完會有10比不同的值)
它的位置在第15行第三段(中間兩段空白)
我想要擷取這10個數字到C槽底下的檔案result.text中

456
562
321
215
...
-----↑類似這樣
並做平均,將平均的值另存成result.txt中,蓋過原來存那10筆資料的檔案。

請問該怎麼寫?
謝謝

fillano iT邦超人 1 級 ‧ 2010-07-01 19:44:10 檢舉
這種問題你用強一點的語言來做啦...例如WSH...
小成 iT邦高手 10 級 ‧ 2010-07-02 08:29:09 檢舉
用for跟set應該可以做到?

你文中說的第三段與前兩段空白是甚麼意思?
段?
測試以 filename 來當讀哪一個檔的變數,
如果檔名有變,就以 i = 1 重新算該行在該檔的行數。
script.awk 檔案內容:
{
  if (filename != FILENAME) {
    filename=FILENAME;
    i=1;
  } else {
    i+=1;
  }

  {print i","$0}

}

執行結果可以用 i 來當每個檔案的第幾行:
awk -F' ' -f script.awk 0*
1,74044 58022
2,06088 61890
3,12958 96936
1,21041 90470
2,82184 60158
3,45002 00804
1,99679 81116
2,63362 90066
3,59551 83714

印出每檔案的第二行的第二個值:
{
  if (filename != FILENAME) {
    filename=FILENAME;
    i=1;
  } else {
    i+=1;
  }
  if (i%2==0) {print $2}
}

累加每檔案第二行的第二個值
{
  if (filename != FILENAME) {
    filename=FILENAME;
    i=1;
  } else {
    i+=1;
  }

  if (i%2==0) {sum+=$2}
}
END { print sum }

根據以上的測試,
該script應改為:
{
  if (filename != FILENAME) {
    filename=FILENAME;
    i=1;
  } else {
    i+=1;
  }
  if (i%15==0) {sum+=$3}
}
END { print sum }

然後執行:
awk -F' ' -f script.awk 0*

即可獲結果。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
6
shunyuan
iT邦研究生 1 級 ‧ 2010-07-01 21:58:15
最佳解答

這個要 PowerShell 才有辦法。

或是 4DOS 或 4NT 才行。

DOS 搞不定。

jason1418 iT邦新手 5 級 ‧ 2010-07-02 15:19:31 檢舉

謝謝您的回應
不過我已經會把東西擷取出來了,但不會加總平均
難道dos連加減乘除都沒辦法ˊˋ?

10
misadm
iT邦高手 10 級 ‧ 2010-07-02 09:19:56

DOS 下的計算可以透過 SET 指令來達成:

<pre class="c" name="code">set /A iValue=((5+4-3)*2)/5

使用參數 /A 來指定等號右方為運算式,結果 iValue 會等於 2(小數點無條件捨去)

至於你說有

C槽裡有10份數據資料,我想從這10份裡面擷取某一個欄位的值

這 10 份數據是什麼?文字檔嗎?檔案內容是否有規則呢?10 份數據擷取資料的邏輯都一樣嗎?『第15行第三段』是什麼意思?可以舉例一下嗎?

可能要請您再加說明一下囉!

jason1418 iT邦新手 5 級 ‧ 2010-07-02 15:24:23 檢舉

文字檔
這是10份文字檔的內容
格式都一樣
我想擷取的是

<pre class="c" name="code">Time per request:       5.376 [ms] (mean, across all concurrent requests)

這一行的數據
將這10個數據加總平均後丟到網路芳鄰上的另外一台上
不知道要怎麼整合寫?
謝謝

misadm iT邦高手 10 級 ‧ 2010-07-02 15:54:49 檢舉

既然您已經知道如果擷取資料,那我就不再贅述。至於您提到要將平均值丟到網路上芳鄰,則可利用:

<pre class="c" name="code">echo %iValue% > \\Host-Name\Share-Name\result.txt

使用大於(導向符號)可以將 iValue 的值寫入 result.txt 之中,上述範例只會保留一筆資料,若要記錄每次資料則可:

<pre class="c" name="code">echo %iValue% >> \\Host-Name\Share-Name\result.txt

連續兩個大於符號,則會保留原來資料。若想註記當時時間則可:

<pre class="c" name="code">echo 資料產生於 %DATE% %TIME% 平均值為:%iValue% >> \\Host-Name\Share-Name\result.txt
misadm iT邦高手 10 級 ‧ 2010-07-02 17:20:29 檢舉

再補充一下:
DOS 的 SET 運算是無法計算小數點的,我看您的資料來源都有小數,這樣就不適合使用批次檔來處理,建議你改用 VBScript 會比較容易。

10
逮丸逮丸
iT邦大師 1 級 ‧ 2010-07-02 21:35:30

最近常有人問有關 Windows 下 Command-Line 的文字處理問題,
想用 Windows 的內建工具解決相當不容易,
只要借助給 Windows 用的 Linux/Unix 的小小工具,
就可隨手就把問題給解掉。

如果各檔案都是用分欄符號分的好好的,
不用 awk 實在是很可惜。

在 Windows 下可裝 Gawk for Windows
只要把 壓縮檔 裡的 bin 目錄裡的 awk.exe 複製到 C:\Windows 裡即可執行。

題目沒給得很具體的例子,
模疑類似原題意的方式,
舉規模較小的例子:
假設每個檔案都固定只有兩行,
(如果每個檔案的行數不一致的話,
要用別的方法來處理)

<pre class="c" name="code"># 檔案 01
74044 58022
06088 61890
# 檔案 02
21041 90470
82184 60158
# 檔案 03
99679 81116
63362 90066

測試印出每個檔的第二欄的值:

<pre class="c" name="code">awk -F' ' '{print $2}' 0*
58022
61890
90470
60158
81116
90066

印出第幾筆資料的順序號及其第二欄的值

<pre class="c" name="code">awk -F' ' '{print NR" "$2}' 0*
1 58022
2 61890
3 90470
4 60158
5 81116
6 90066

測試抓每個檔第二行第二個值:

<pre class="c" name="code">
awk -F' ' '{ if (NR%2 == 0) {print $2} }' 0*
61890
60158
90066
# 假設要把每個檔案的第二行的第二個值做加總及其平均:
awk -F' ' '{ if (NR%2 == 0) {sum+=$2} } END {print sum}' 0*
212114
awk -F' ' '{ if (NR%2 == 0) {sum+=$2} } END {print sum/3}' 0*
70704.7

簡單說明一下:
NR 是 Number of Record 讀入檔案的第幾筆資料,
也可看作是第幾行。
-F' ' 是定義分欄號是空格,
$2 是分欄第二個值,$0 是整行。
sum 是自己命名的變數名稱,
在此用來加總每個第二欄的值用。
END 後半段是前面動作完成後,
再額外作的動作。
awk 的教學連結,可參考 [好用的 Script] 老工具 Perl, AWK, SED的還不錯的資源

如果是要:> 它的位置在第15行第三段(中間兩段空白)

<pre class="c" name="code">awk -F' ' '{ if (NR%15 == 0) {sum+=$3} } END {print sum/10}' 0*

就可印出所要的結果,
或者用 > 或 >> 寫到指定的檔案裡。

上述 awk 的作法有一個問題:
如果要抓的值不是該檔的最後一行,
這樣 NR%15 就不會是落在每一檔的第15行。
因NR是把所有檔來做累計。
所以增用另一個 i 為索引,來指出每個檔案的第幾行。
FILENAME 是 awk 的內建變數,
自建個 filename 來存該行所屬哪個 FILENAME,
若 filename != FILENAME時,
就把 i = 1,知道是換了個檔案,而從第一行算起。

所以修改成:討論裡的說明

我要發表回答

立即登入回答