Bash

將一列epochs轉換為從0開始的時間列

  • February 11, 2016

是)我有的

嗨,想像一下很多這樣的文件,其中第一列是紀元,其他列是一些數據:

1000333,34,1
1001456,56,0
1005356,34,2

我需要的

我需要將它們轉換為:

0,34,1
1123,56,0
5023,34,2

上述第一列編號來自:

1000333 - 1000333 =    0
1001456 - 1000333 = 1123
1005356 - 1000333 = 5023

語境

這些文件在幾個文件夾中放入一個名為 的大文件夾logs_swapoff中,它們以_times.csv(這些文件夾中還有另一個csvs 不能碰)結尾。

文件範例:

logs_swapoff/folder1/modifyMe_times.csv
logs_swapoff/folder1/dontTouchMe_cores.csv
logs_swapoff/folder2/modifyMeToo_times.csv

我打算在 bash 中使用這個循環,但我不知道如何完成任務本身。

for filename in $(find logs_swapoff/* -name '*_times.csv') ; do
   # filename without extension (to write the output with a similar name?)
   fname=$(dirname $filename`"/"`basename -s .csv $filename);

   ?????

done;

多謝你們 :)

列舉文件

解析的輸出find是脆弱的。最好find呼叫轉換程序。要生成輸出文件名,一個簡單的參數擴展就足以將後綴_times.csv改為_subtracted.csv(例如)。

find logs_swapoff -name '*_times.csv' -exec sh -c '
 <"$1" awk "$0" >"${1%_times.csv}_subtracted.csv"
' '…' {} \;

'…'是要執行的 awk 程式碼。我把它放在 shell 片段之外以簡化引用。

轉換每個文件

您需要逐行處理文件,並在每一行上進行涉及一些算術的簡單文本轉換。這使得 awk 成為這項工作的理想工具。範例輸出的唯一困難是您似乎想要對齊最小寬度;如果不首先讀取整個文件以確定最大寬度,就無法做到這一點。如果您對一些額外的空格感到滿意,您可以逐行處理文件。

awk '
   NR==1 {start = $1}
   {n = $1 - start; sub(/^ *[0-9]+/, ""); printf "%6d", n; print}
'

說明:在第一行,將start變數設置為第一個數字。然後,在每一行上,start從第一個數字中減去 的值,然後去掉第一個數字。列印減法的結果(用空格填充到 6 個字元)和該行的其餘部分。

此程式碼假定第一個數字後總是有空格。如果不是這種情況,您可以進行更精確的匹配。

awk '
   NR==1 {match(/[0-9]+/); start = substr(RSTART, RLENGTH)}
   match(/[0-9]+/) {n = substr(RSTART, RLENGTH) - start; sub(/ *[0-9]+/, ""); printf "%6d", n; print}
'

如果欄位是逗號分隔的並且沒有空格需要擔心,請將逗號聲明為欄位分隔符。然後,您可以簡單地用更新的值替換第一個欄位。

awk -F, '
   NR==1 {start = $1}
   {$1 = $1 - start; print}
'

所以把它們放在一起(逗號版本):

find logs_swapoff -name '*_times.csv' -exec sh -c '
 <"$1" awk -F, "$0" >"${1%_times.csv}_subtracted.csv"
' '
   NR==1 {start = $1}
   {$1 = $1 - start; print}
' {} \;

引用自:https://unix.stackexchange.com/questions/261381