我拥有的
您好,想象一下很多这样的文件,其中第一列是纪元,其他列是一些数据:
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.csv
csv
文件示例:
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}
' {} \;