我拥有的

我拥有的

我拥有的

您好,想象一下很多这样的文件,其中第一列是纪元,其他列是一些数据:

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

语境

这些文件被分成几个文件夹,放入一个名为 的大文件夹中,它们以(这些文件夹中还有另一个s 不得触及)logs_swapoff结尾。_times.csvcsv

文件示例:

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;

多谢你们 :)

答案1

枚举文件

解析 的输出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}
' {} \;

相关内容