Scripting 如何使用sed或awk删除符合特定字段条件的行?
我有以下数据:Scripting 如何使用sed或awk删除符合特定字段条件的行?,scripting,sed,awk,Scripting,Sed,Awk,我有以下数据: 1 abc xyz - - 2 mno 2 lnm dse - - 3 pqr 3 ebe aaa xhd asw 4 pow 4 abc fww wrw ffp 3 ffw 我想删除满足以下两个条件的行: 第4列和第5列为空 对应行的行号不包含在任何其他行的第6列中 在这种情况下,应删除第1行。在这种情况下,如何使用sed/awk或最合适的脚本语言执行此操作。使用perl的
1 abc xyz - - 2 mno
2 lnm dse - - 3 pqr
3 ebe aaa xhd asw 4 pow
4 abc fww wrw ffp 3 ffw
我想删除满足以下两个条件的行:
在这种情况下,应删除第1行。在这种情况下,如何使用sed/awk或最合适的脚本语言执行此操作。使用
perl
的可能解决方案:
script.pl的内容:
use warnings;
use strict;
## Accept one argument, the input file.
@ARGV == 1 or die qq[Usage: perl $0 input-file\n];
my ($lines, %hash);
## Process file.
while ( <> ) {
## Remove leading and trailing spaces for each line.
s/^\s*//;
s/\s*$//;
## Get both indexes.
my ($idx1, $idx2) = (split)[0,5];
## Save line and index1.
push @{$lines}, [$_, $idx1];
## Save index2.
$hash{ $idx2 } = 1;
}
## Process file for second time.
for ( @{$lines} ) {
## Get fields of the line.
my @f = split /\s+/, $_->[0];
## If fourth and fifth fields are empty (-) and first index exists as second
## index, go to next line without printing.
if ( $f[3] eq qq[-] && $f[4] eq qq[-] && ! exists $hash{ $_->[1] } ) {
next;
}
## Print line.
printf qq[%s\n], $_->[0];
}
结果:
2 lnm dse - - 3 pqr
3 ebe aaa xhd asw 4 pow
4 abc fww wrw ffp 3 ffw
也许像这样的事情可以奏效-
awk 'NR==FNR{a[$6];next}
($4 ~ /[- ]/ && $5 ~ /[- ]/) && !($1 in a){next}1' file file
条件:
如果第4列和第5列为空,并且第6列中没有索引,我们将跳过该行并打印其他所有内容
说明:
我们使用NR
和FNR
内置变量,并将同一文件传递两次。在第一次运行中,我们扫描文件并将列6
存储在一个数组中next
用于防止第二个pattern{action}
语句在读取第一个文件之前运行。一旦文件被完全读取,我们将根据您的条件测试同一文件。如果第4列和第5列为空,我们查看索引,如果它不在数组中,则使用next
跳过该行,否则我们将打印它
测试:
这可能适合您:
sed -rn 's/^.*(\S+)\s+\S+$/\1/;H;${x;s/^|\n/:/gp}' file |
sed -r '1{h;d};/^(\s*\S*){3}\s*-\s*-/{G;/^\s*(\S*).*:\1:/!d;s/\n.*//}' - file
2 lnm dse - - 3 pqr
3 ebe aaa xhd asw 4 pow
4 abc fww wrw ffp 3 ffw
说明:
读取该文件并从第6列构建一个查找表,该列由分隔:
将表格(第一行)读入保持空间(HS),然后再次读取文件
当第5列和第6列仅包含-
时
- 将查找表追加到模式空间(PS)
- 使用第一列作为键进行查找,如果失败,则删除该列
线路
- 对于所有剩余的行,删除查找表
问题的标题是问一些与问题正文正交的问题。根据您的两个标准,应删除示例中的前两行,因为第一列和第六列都不相等。第一个和第二个要求之间的关系是“和”“不”“或”。根据您更新的示例,为什么第2行没有被删除?第4和第5个字段均为“空白”,其“索引值”为2(如果不包含在第6列中)(3)第2行不会被删除,因为其索引2包含在第一行的第6列中。谢谢SiegeX.)圣诞快乐!!实际上,有一个逻辑错误。第二个条件应该是逻辑OR,因为您否定了匹配项($4!~/[-]/| |$5!~/[-]/)
,所以我更正了它。而且,我意识到不需要为数组编制索引。简单的a[$6]+
就足够了。谢谢!:)我读了OP最后的评论。已经修改了awk
的第二部分。实际上,您甚至不需要增加它,只要a[$6]
就足够了。当我意识到我需要查看两次文件后,我正在重做我的答案,但我使用的是END{},它太长了,我知道必须有更好的方法。将同一个文件传递两次并使用NR==FNR
绝对是更好的方法。看来你今天键盘玩得不好
[jaypal:~/Temp] cat file
1 abc xyz - - 2 mno
2 lnm dse - - 3 pqr
3 ebe aaa xhd asw 4 pow
4 abc fww wrw ffp 3 ffw
[jaypal:~/Temp] awk 'NR==FNR{a[$6];next} ($4 ~ /[- ]/ && $5 ~ /[- ]/) && !($1 in a){next}1' file file
2 lnm dse - - 3 pqr
3 ebe aaa xhd asw 4 pow
4 abc fww wrw ffp 3 ffw
sed -rn 's/^.*(\S+)\s+\S+$/\1/;H;${x;s/^|\n/:/gp}' file |
sed -r '1{h;d};/^(\s*\S*){3}\s*-\s*-/{G;/^\s*(\S*).*:\1:/!d;s/\n.*//}' - file
2 lnm dse - - 3 pqr
3 ebe aaa xhd asw 4 pow
4 abc fww wrw ffp 3 ffw