我到处都看到过类似的问题,但似乎没有一个接近我想要实现的目标。
我有一个动态 csv 文件(制表符分隔符),每小时都会更新/附加 但注意: 只有 HEADER 1 和 HEADER 2 下面的行数每小时都会增加。请看下面两个例子作为参考
FileA.csv 示例 第 3 小时
HEADER 1 NUM
hour 1 5
hour 2 10
hour 3 15
HEADER 2 NUM
hour 1 3
hour 2 6
hour 3 9
HEADER 3 NUM
age 23
bus 21
pig 07
dog 40
FileA.csv 示例第 7 个小时
HEADER 1 NUM
hour 1 5
hour 2 10
hour 3 15
hour 4 20
hour 5 25
hour 6 30
hour 7 35
HEADER 2 NUM
hour 1 3
hour 2 6
hour 3 9
hour 4 12
hour 5 15
hour 6 18
hour 7 21
HEADER 3 NUM
age 13
bus 28
pig 85
dog 55
标题 1 和标题 2 下面的行每小时都会增加。标题 3 及以下是唯一保持不变的内容
所以我想要实现的只是将 FileA.csv 分成 ABC.csv , DEF.csv , GHI.csv
使用第三个小时的例子来参考我想要实现的目标
ABC.csv
HEADER 1 NUM
hour 1 5
hour 2 10
hour 3 15
DEF.csv
HEADER 2 NUM
hour 1 3
hour 2 6
hour 3 9
GHI.csv
HEADER 3 NUM
age 23
bus 21
pig 07
dog 40
下面是我尝试使用 grep 执行的操作,但我无法结合 grep 和 cut 来实现此目的。我尝试过使用 Sed 但不知道如何在搜索后剪切和移动它。我知道这可以用 awk 实现,但 awk 并不强大
请帮忙。谢谢
假设标题字面上有“HEADER ...”行,如上所述, 你能尝试一下吗:
awk '
BEGIN { # define filenames to write
fname[1] = "ABC.csv"; fname[2] = "DEF.csv"; fname[3] = "GHI.csv"
}
/^HEADER/ { # reached the header line
if (c >= 1) close(file) # close the previous file, if opened
file = fname[++c] # update the filename to write
}
{
print > file # append to the file
}
' FileA.csv
顺便说一句,文件正在增长的事实似乎与 文件分割。
你可以写这样的东西。您不需要 awk、sed 或 grep。 Bash 本身可以为你做到这一点。
#!/bin/bash
FILE=FileA.csv
OUTPUT=ABC.csv
while read CMD; do
if [[ "$CMD" == HEADER*1*NUM ]]; then
OUTPUT=ABC.csv
elif [[ "$CMD" == HEADER*2*NUM ]]; then
OUTPUT=DEF.csv
elif [[ "$CMD" == HEADER*3*NUM ]]; then
OUTPUT=GHI.csv
fi
echo "$CMD" >> $OUTPUT
done < "$FILE"
echo "Done"
chmod 755 test.sh
./test.sh
ABC.csv
HEADER 1 NUM
hour 1 5
hour 2 10
hour 3 15
DEF.csv
HEADER 2 NUM
hour 1 3
hour 2 6
hour 3 9
GHI.csv
HEADER 3 NUM
age 23
bus 21
pig 07
dog 40
我们循环遍历文件的每一行。如果我们看到 HEADER 1 NUM,我们就说这些行应该写入 ABC.csv。如果该行有 HEADER 2 NUM,我们说这些行应该写入 DEF 等等。
然后我们将这些行写入相应的文件。
例如
>>
表示附加到 ABC.csv 文件。因此,HEADER 1 NUM 被写入该文件如果要删除 ABC、DEF 和 GHI 文件,可以在脚本中的
rm ABC.csv DEF.csv, GHI.csv
行之前或之后写入 FILE=FileA.csv
。这样,您始终会获得全新的文件。
如果您不关心确切的输出文件名并且您有 GNU
awk
,您可以尝试以下操作:
awk 'BEGIN {RS = "HEADER[^\n]*[\n]"}
NR>1 {printf("%s%s",p,$0)>"File" NR-1 ".csv"} {p=RT}' FileA.csv
输出文件名称为
File1.csv
、File2.csv
、... 如果您绝对想要 ABC.csv
、DEF.csv
、GHI.csv
,您可以使用:
awk -v f="ABC.csv DEF.csv GHI.csv" '
BEGIN {RS = "HEADER[^\n]*[\n]"; split(f,files)}
NR>1 {printf("%s%s",p,$0)>files[NR-1]} {p=RT}' FileA.csv