如果列 Y 和列 Z 不等于 NULL,则修剪列 X 留下特定数量的字符

如果列 Y 和列 Z 不等于 NULL,则修剪列 X 留下特定数量的字符

我正在尝试找到一种方法,使用 awk/sed 过滤 csv 以截断特定列(例如第 1 列)中的值,以保留最后 8 个字符并用通配符替换开头,前提是其他两个特定列不是等于 NULL - 例如第 3 列和第 5 列

示例数据:

1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,DATA,DATA

会成为:

1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*.filename2.exe,NULL,DATA,DATA,DATA,DATA

我使用一系列的 pippingrev和编写了这个脚本cut,但效率非常低,而且我正在学习更高级awk/sed过滤器,因为我正在处理大量数据,并且脚本需要几个小时。

答案1

awk -v c=8 'BEGIN{ FS=OFS="," }
$3!="NULL" && $5!="NULL"{ $1=(length($1)>c?"*"substr($1,length($1)-c+1):$1) }1' infile

在这里,仅当列#1 的长度> 8 个字符(您可以更改c=#要保留的字符数)时,我们才添加“*”,否则打印列#1 不变。

答案2

使用perl:

  1. 替换第一个字段中直到_字符、逻辑 AND ( &&) 的所有内容 - 即两者都不能为“NULL”:
$ perl -F, -pe 's/^.*?_/*/ if ($F[2] ne "NULL" && $F[4] ne "NULL")' input.csv 
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*filename2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA

这使用了 perl 的“非贪婪”?量词 with ,.*以便它只匹配第一个(大概是唯一的)下划线字符。

  1. 替换第一个字段中直到_字符、逻辑或 ( ||) 的所有内容,即其中一个或两个都不能为“NULL”:
$ perl -F, -pe 's/^.*?_/*/ if ($F[2] ne "NULL" || $F[4] ne "NULL")' input.csv 
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*filename2.exe,NULL,DATA,DATA,DATA,DATA
*filename2.exe,NULL,NULL,DATA,DATA,DATA
*filename2.exe,NULL,DATA,DATA,NULL,DATA
  1. 替换第一个字段除最后 8 个字符之外的所有字符,逻辑 AND:
$ perl -F, -pe 's/^.*?(.{8}),/*$1,/ if ($F[2] ne "NULL" && $F[4] ne "NULL")' input.csv 
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*ame2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA

这使用捕获组(.{8})来提取第一个字段的最后 8 个字符,并将它们用于替换字符串 ( $1)。

  1. 替换第一个字段除最后 8 个字符之外的所有字符,逻辑或:
$ perl -F, -pe 's/^.*?(.{8}),/*$1,/ if ($F[2] ne "NULL" || $F[4] ne "NULL")' input.csv 
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*ame2.exe,NULL,DATA,DATA,DATA,DATA
*ame2.exe,NULL,NULL,DATA,DATA,DATA
*ame2.exe,NULL,DATA,DATA,NULL,DATA
  1. 替换除最后 8 个字符之外的所有字符基本名称文件名的一部分(即“扩展名”之前),逻辑 AND。
$ perl -F, -pe 's/^.*?(.{8})\./*$1./ if ($F[2] ne "NULL" && $F[4] ne "NULL")' input.csv 
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*ilename2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA

注意:文件名“扩展名”在 unix 和 linux 文件系统中并不那么重要。此外,它们并不像古老的 MS-DOS FAT 文件系统那样限制为 3 个字符,而且可以有多个字符 - 现代 Windows 文件系统也是如此。如果文件名.中包含多个字符,则此版本将无法按照您的预期工作。

  1. 现在逻辑“或”版本应该很明显了。

注意:perl 数组从 0 开始,而不是 1。这就是为什么第三个字段在 中$F[2],第五个字段在 中$F[4]

另外,我在示例输入中添加了两行,以显示使用 AND 和 OR 之间的区别。

$ cat input.csv 
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA

输入的第三行和第四行与您的第二行相同,只是在第3行,字段3中的“DATA”已更改为“NULL”,在第4行,字段5中的“DATA”已更改为“无效的。

答案3

#!/usr/bin/python
import re
k=open('filepath','r')
for i in k:
    kospl=i.strip().split(',')
    if (kospl[2] != "NULL"  and kospl[4] != "NULL" and kospl[0] >8):
        lk=len(kospl[0])-13
        k="*."+kospl[0][lk:]+","
        print k+",".join(kospl[1:])
    else:
        print i.strip()
~                                 

输出

1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*.filename2.exe,NULL,DATA,DATA,DATA,DATA

相关内容