1529.89 1.05 22.36 48.78 33.8
1529.91 2.05 22.36 52.79 36.93
1529.92 3.06 22.36 52.80 36.93
1529.92 4.25 22.36 52.79 36.94
1529.92 5.10 22.36 52.79 36.94
1529.93 5.24 22.36 52.80 36.94
1529.94 6.05 22.36 52.80 36.94
1529.95 6.27 22.36 52.80 36.94
1529.95 7.01 22.36 52.80 36.94
1529.96 7.26 22.36 52.80 36.94
1529.97 8.11 22.36 52.80 36.94
1529.99 9.22 22.35 52.80 36.94
1530.00 10.12 22.36 52.80 36.94
1530.02 11.26 22.36 52.80 36.94
1530.03 12.18 22.36 52.80 36.94
1530.04 13.12 22.36 52.81 36.94
1530.06 14.04 22.36 52.81 36.95
1530.10 16.21 22.36 52.81 36.94
1530.11 17.17 22.35 52.80 36.94
1530.12 18.09 22.35 52.81 36.94
1530.14 19.19 22.35 52.81 36.94
1530.15 20.19 22.35 52.80 36.94
1530.17 21.24 22.35 52.81 36.94
1530.18 22.05 22.35 52.81 36.95
1530.20 23.14 22.35 52.81 36.95
1530.21 24.14 22.35 52.81 36.94
1530.23 25.23 22.35 52.80 36.94
1530.23 26.03 22.35 52.80 36.94
1530.23 26.24 22.34 52.80 36.94
1530.26 27.10 22.35 52.81 36.95
我有这种类型的文件。我需要的是,如果第二个字段中的整数不等于前一行第二个字段中的相同数字,则打印它的每一行,例如下面两行:
1529.94 6.05 22.36 52.80 36.94
1529.95 6.27 22.36 52.80 36.94
...我想只打印第一行并跳过第二行。第二个字段编号增加到约 1300,然后减少到 1。
我尝试使用 awk substr() 函数,但它似乎不起作用,因为我卡住了:
awk -F. '{for (i=NR;i<3814;i++) {i=1 n=(substr($2,4))}{i=i+1 v=(substr($2,4))} {if ((n+v)%2=1) print $0} {i++}}' test.csv
答案1
抱歉,你的awk
回答完全没有帮助,它与你表达的要求完全不同。
- 您的字段分隔符可能不是“.”但空间
- 解析您不需要的十进制数
substr()
- 将小数舍入为整数,只需
int()
所以代码看起来像这样:
awk 'int($2)!=prev{
print
prev=int($2)
}'
要使其成为一行,您需要一个“;”
awk 'int($2)!=prev{print;prev=int($2)}'
结果是:
1529.89 1.05 22.36 48.78 33.8
1529.91 2.05 22.36 52.79 36.93
1529.92 3.06 22.36 52.80 36.93
1529.92 4.25 22.36 52.79 36.94
1529.92 5.10 22.36 52.79 36.94
1529.94 6.05 22.36 52.80 36.94
1529.95 7.01 22.36 52.80 36.94
1529.97 8.11 22.36 52.80 36.94
1529.99 9.22 22.35 52.80 36.94
1530.00 10.12 22.36 52.80 36.94
1530.02 11.26 22.36 52.80 36.94
1530.03 12.18 22.36 52.80 36.94
1530.04 13.12 22.36 52.81 36.94
1530.06 14.04 22.36 52.81 36.95
1530.10 16.21 22.36 52.81 36.94
1530.11 17.17 22.35 52.80 36.94
1530.12 18.09 22.35 52.81 36.94
1530.14 19.19 22.35 52.81 36.94
1530.15 20.19 22.35 52.80 36.94
1530.17 21.24 22.35 52.81 36.94
1530.18 22.05 22.35 52.81 36.95
1530.20 23.14 22.35 52.81 36.95
1530.21 24.14 22.35 52.81 36.94
1530.23 25.23 22.35 52.80 36.94
1530.23 26.03 22.35 52.80 36.94
1530.26 27.10 22.35 52.81 36.95
正确的 ?
答案2
如果您不介意使用sed
:
sed -E '1p;N;/^[^ ]+ +([0-9]+)\..*\n[^ ]+ +\1\./D;h;s/.*\n//p;x;$d;D' test.csv
使用该N;P;D
模式,您总是同时处理两行。长正则表达式是在第二个字段中找到整数相同的两行,然后继续下一行,否则打印第二行并继续。根据要求提供更详细的解释。
如果您的字段分隔符是制表符而不是空格,只需调整模式即可。
答案3
使用乐(以前称为 Perl_6):第二个示例
raku -e 'my @a = lines.rotor(2 => -1); for @a {.[0].put if .words[1].Int != .words[6].Int};'
或者
raku -e 'my @a = lines.rotor(2 => -1); for @a -> $a {$a.[0].say when $a.words[1].Int != $a.words[6].Int };'
上面的 Raku 代码是对 OP 标题的相当字面的解释。使用 来连接成对的线rotor
,创建重叠,使得线0,1
成对、1,2
成对、2,3
成对等。对于@a
包含成对线的数组的每个位置,执行条件测试Int
第二列的 eger 等价性。如果Int
s 不相等,则配对行的第一个元素(行)为 out- put
。
这种方法的一个警告是rotor
默认情况下仅返回完全“分组”的元素。因此,任何尾随的“元素簇”都会从@a
数组中删除。问题的标题是“...当前行和前一行的字段之间的简单数学计算...”,但这个答案强制严格配对(最后一行是未配对的)。希望这个答案在任何情况下都有用。
示例输出:
1529.89 1.05 22.36 48.78 33.8
1529.91 2.05 22.36 52.79 36.93
1529.92 3.06 22.36 52.80 36.93
1529.92 4.25 22.36 52.79 36.94
1529.93 5.24 22.36 52.80 36.94
1529.95 6.27 22.36 52.80 36.94
1529.96 7.26 22.36 52.80 36.94
1529.97 8.11 22.36 52.80 36.94
1529.99 9.22 22.35 52.80 36.94
1530.00 10.12 22.36 52.80 36.94
1530.02 11.26 22.36 52.80 36.94
1530.03 12.18 22.36 52.80 36.94
1530.04 13.12 22.36 52.81 36.94
1530.06 14.04 22.36 52.81 36.95
1530.10 16.21 22.36 52.81 36.94
1530.11 17.17 22.35 52.80 36.94
1530.12 18.09 22.35 52.81 36.94
1530.14 19.19 22.35 52.81 36.94
1530.15 20.19 22.35 52.80 36.94
1530.17 21.24 22.35 52.81 36.94
1530.18 22.05 22.35 52.81 36.95
1530.20 23.14 22.35 52.81 36.95
1530.21 24.14 22.35 52.81 36.94
1530.23 25.23 22.35 52.80 36.94
1530.23 26.24 22.34 52.80 36.94
答案4
使用乐(以前称为 Perl_6)
raku -e 'my @a = lines.map(*.words); my %seen; for @a[*].map(*.[1].Int) { \
%seen.=append: ( $_ => $++ ) }; for %seen.values.map(*.min).sort -> $a { \
@a[$a].join("\t").put };'
或者
raku -e 'my @a = lines>>.words; my @b = @a.map(*.[1].Int).pairs.unique( :as(*.value) ); \
@b.=map(*.key); for @b -> $a {@a[$a].join("\t").put};'
简而言之,lines
被单独分解成单词,并存储在@a
数组中。
(上面的第一个例子):%seen
声明了一个散列。对于每行的第二列,它被转换为Int
,并且每个都成为使用粗箭头语法的Int
键/值对,其中as 键和零索引行号为。这些键/值对被附加到哈希中。由于哈希的键必须是唯一的,因此多个行号会添加到同一个键中。最后,通过迭代哈希值并提取行号,并将其用作位置索引来仅打印数组的匹配行,从而输出数据。=>
Int
value
%seen
Int
put
%seen
values
min
$a
@a[$a]
@a
上面的第二个示例:每行的第一列被转换为Int
,并且这些进一步被转换为pairs
,其中行号作为键和Int
值。pairs
然后将它们unique
在此基础上进行比较:as(*.value)
。然后通过用每个数组元素单独覆盖@b
数组来恢复行号。这些s 如上所述用于索引行数组。@b.=map(*.key)
key
key
@a
示例输出:
1529.89 1.05 22.36 48.78 33.8
1529.91 2.05 22.36 52.79 36.93
1529.92 3.06 22.36 52.80 36.93
1529.92 4.25 22.36 52.79 36.94
1529.92 5.10 22.36 52.79 36.94
1529.94 6.05 22.36 52.80 36.94
1529.95 7.01 22.36 52.80 36.94
1529.97 8.11 22.36 52.80 36.94
1529.99 9.22 22.35 52.80 36.94
1530.00 10.12 22.36 52.80 36.94
1530.02 11.26 22.36 52.80 36.94
1530.03 12.18 22.36 52.80 36.94
1530.04 13.12 22.36 52.81 36.94
1530.06 14.04 22.36 52.81 36.95
1530.10 16.21 22.36 52.81 36.94
1530.11 17.17 22.35 52.80 36.94
1530.12 18.09 22.35 52.81 36.94
1530.14 19.19 22.35 52.81 36.94
1530.15 20.19 22.35 52.80 36.94
1530.17 21.24 22.35 52.81 36.94
1530.18 22.05 22.35 52.81 36.95
1530.20 23.14 22.35 52.81 36.95
1530.21 24.14 22.35 52.81 36.94
1530.23 25.23 22.35 52.80 36.94
1530.23 26.03 22.35 52.80 36.94
1530.26 27.10 22.35 52.81 36.95