我有一个只有 2 列的 CSV 文件(但是地段行)以及偶尔出现的不规则行,该行始终以星号 (*) 字符开头,并且可能跨越两列以上。仅使用 Linux 命令行,预期行为是:
- 如果 3 个或更多连续数据行的第二列值相同,则删除中间行。保留起始行和结束行。
- 保留以星号开头的不规则行
例如,如果我有一个包含以下内容的 CSV:
0,Apple
1,Apple
2,Apple
* Checkpoint
* Another checkpoint
3,Apple
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
10,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
14,Citrus
15,Citrus
16,Citrus
17,Apple
18,Citrus
之后应该如下所示:
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
16,Citrus
17,Apple
18,Citrus
在上面的示例中,第 1 至 3 行、第 10 行和第 14 至 15 行被删除。
预先非常感谢您的任何答复。
干杯
答案1
使用awk
:
BEGIN { FS = "," }
/^[*]/ { print; next }
{
if (NR > 1 && $2 == word) {
tail = $0
++count
} else {
if (count) print tail
word = $2; count = 0
print
}
}
END { if (count) print tail }
该awk
脚本无条件打印所有以 开头的行*
。如果该行不是这样的行,并且如果第二个字段中的单词是我们记住的单词,则将该记录存储在变量中tail
(“tail”,如一系列记录中具有相同单词的最后一条记录)第二个字段)。
如果第二个字段是不是与之前相同,然后打印尾部记录,如果上一运行记录中有多个记录,则记住新单词并打印当前记录(新运行的一个或多个记录中的第一个记录)第二个字段中的相同单词)。
根据提供的数据进行测试并假设它是简单的 CSV(意味着没有嵌入的分隔符或换行符等):
$ awk -f script file
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
16,Citrus
17,Apple
18,Citrus
与上面类似但使用米勒 ( mlr
),它支持 CSV,并且能够处理带有复杂引号字符串的 CSV 记录:
if (is_not_null(@word) && $2 == @word) {
@tail = $*;
false # omit this record for now
} else {
is_not_null(@tail) {
emit @tail # emit the tail record
}
@word = $2; @tail = null;
true # emit this record
}
end { is_not_null(@tail) { emit @tail } }
filter
这是 Miller子命令的表达式,用于使用与awk
上述代码非常相似的逻辑来包含或省略输入数据集中的记录。我们可以*
通过--pass-comments-with='*'
命令行中的use来让 Miller 遍历以该字符开头的行。使用--csv
with-N
将输入视为无标头 CSV。
$ mlr --pass-comments-with='*' --csv -N filter -f script file
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint," * Leftover checkpoint note 1"," * Leftover checkpoint note N"
16,Citrus
17,Apple
18,Citrus