我有一个大约有 12000 行的文件。
pk=91001011964;fck=85;fcv=true;fpi=1;fci=cacf;fmd=1422745568,;fck=83;fcv=decoccm;fpi=1;fci=cacf;fmd=1423070648,;fck=87;fcv=false;fpi=1;fci=cacf;fmd=1422745568,;fck=86;fcv=true;fpi=1;fci=cacf;fmd=1422745568,;fck=35;fcv=54bed48ad84397433fef0a350d65a893;fpi=1;fci=cacf;fmd=1422745568,;fck=83;fcv=travide;fpi=1;fci=cacf;fmd=1422811693,;fck=88;fcv=true;fpi=1;fci=cacf;fmd=1422745568,;fck=84;fcv=10;fpi=1;fci=cacf;fmd=1422745568;vpi=ppi=1;pci=cacf;pmd=1423070648;pos=null;pod=0;pso=null;psd=0;vos=null
pk=91001045537;fck=86;fcv=true;fpi=1;fci=cacf;fmd=1421428238,;fck=85;fcv=true;fpi=1;fci=cacf;fmd=1421428238,;fck=87;fcv=false;fpi=1;fci=cacf;fmd=1421428238,;fck=88;fcv=true;fpi=1;fci=cacf;fmd=1421428238,;fck=84;fcv=10;fpi=1;fci=cacf;fmd=1421428238,;fck=35;fcv=cd9b9ed4fc167d8007dd9544114bc83f;fpi=1;fci=cacf;fmd=1421428238,;fck=83;fcv=demelog;fpi=1;fci=cacf;fmd=1421557377;vpi=ppi=1;pci=cacf;pmd=1421557377;pos=null;pod=0;pso=null;psd=0;vos=null
pk=91001440737;fck=86;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=85;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=87;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=88;fcv=true;fpi=1;fci=cacf;fmd=1421687966,;fck=84;fcv=10;fpi=1;fci=cacf;fmd=1421687966,;fck=35;fcv=7360072ca14cb5d5578a3902fbe51792;fpi=1;fci=cacf;fmd=1421687191;fck=78;fcv=de724a544277d79c14d19809fe51ab71;fpi=1;fci=cacf;fmd=1421687966,;fck=83;fcv=demelog;fpi=1;fci=cacf;fmd=1421816564;vpi=ppi=1;pci=cacf;pmd=1421816564;pos=null;pod=0;pso=null;psd=0;vos=null
我需要解析文件,在行中以特定顺序查找特定字符串值,然后打印或选择该行最接近的列。如果该字符串值不存在,则打印空列。
假设我有fck=35
。如果存在,则打印搜索到的字符串和最接近的 fmd。对于第 3 行,它将是fck=35;fmd=1421687191
.如果fck=35
不存在,则添加一个空列,这将使fck=35;;
假设我正在照顾 for fck=78
。如果确实存在,则打印搜索到的字符串和最接近的 fmd。对于第 3 行,我将有fck=78;fmd=1421687966
.如果fck=78
不存在,则添加一个空列,这将使fck=78;;
.
其他条件如下
For fck=84 look for the next fcv For fck=85 look for the next fcv For fck=86 look for the next fcv For fck=83 look for the next fcv
fck=83 的下一个 fcv 可以是 naismc、decoide、decoccm、travide、travccm 或 mariccm
我将使用第 3 行作为示例:
fck=35;fmd=1421687191;fck=78;fmd=1421687966;fck=84;fcv=10;fck=85;fcv=true;fck=86;fcv=true;fck=83;fcv=demelog
或者(如果缺少 fmd 或 fcv 或至少缺少一些:这部分不再是第 3 行,只是我没有在示例中放入的另一行,但我想这并不重要)
fck=35;;fck=78;;fck=84;fcv=10;fck=85;fcv=true;fck=86;;fck=83;fcv=demelog
我正在考虑在awk
or中执行此操作sed
。但我怀疑它的威力有多大,而且就我到目前为止所看到的而言,它没有帮助。也许Python可以做到这一点,但我对Python很不熟悉。
欢迎任何帮助。
我的一个朋友帮我解决了这个问题
awk -F\; -v fck=78 '{for (i=1;i<=NF;i++) if($i=="fck="fck) print "fck="fck";"$(i-1)}' name_of_the_file
正如你所看到的,当我需要满足上述所有条件时,它只需要一个条件,这里 fck=78 。
任何关于我可以改进这个小脚本的提示或任何可以产生影响的东西都会很棒。但另一个脚本是可能的。我正在考虑Python,但我不确定如何做到这一点。
TIA
答案1
我假设您有一个包含您正在查找的各种字符串的文件。像这样的东西:
fck=35 fmd
fck=78 fcv
bnv=12 fcv
对于其中的每一个,您想要搜索文件,并且如果一行与任何模式匹配,则您需要fmd
匹配字符串后面的第一个值。如果是这样,我会在 perl 中执行如下操作:
#!/usr/bin/env perl
## Open the list of search patterns.
## The script expects it to be the 1st argument.
open(my $list,"$ARGV[0]");
## Read the file and save the patterns
## in the %pat hash.
while (<$list>) {
## remove trailing newlines
chomp;
## separate the search pattern from the target
my @fields=split(/\s+/);
## Save the search pattern and accompanying target in
## in the hash (%pats).
$pats{$fields[0]}=$fields[1];
}
## Open the list of search patterns.
## The script expects it to be the 2nd argument.
open(my $file,"$ARGV[1]");
## Read the file
while (<$file>) {
## split the line on ';' into the @fields array
my @fields=split(/;/);
## This is the string that will be printed for
## the current line.
my $outstring="";
## Check each of the search patterns against
## each of the fields.
foreach my $pat(keys(%pats)) {
## Add the pattern to the outstring
$outstring.="$pat;";
## save all all 1st fmd values that follow
## this pattern.
my @matches= ( /$pat.+?($pats{$pat}=[^;]+)/g );
## Add this pattern's matches to the output string.
$outstring.= join(";",@matches) . ";";
}
## Print the output string for this line
print "$outstring\n";
}
例如,如果将上面的脚本保存parser.pl
在您的文件中$PATH
并使其可执行 ( chmod 755 ~/bin/parser.pl
),则可以像这样运行它:
$ parser.pl list.txt file.txt
bnv=12;;fck=35;fmd=1422745568,;fck=78;;
bnv=12;;fck=35;fmd=1421428238,;fck=78;;
bnv=12;;fck=35;fmd=1421687191 fmd=1111111111;fck=78;fcv=de724a544277d79c14d19809fe51ab71;
答案2
如果您正在寻找最接近的列并且知道分隔符,这对于 grep 和 sed 来说应该是一个简单的任务。
grep -e "fck=35"
将返回整行 fck=35 is on。然后将其通过管道传输到两个 sed 以获得您想要的内容。
grep -e "fck=35" | sed s/.*fck=35;//g | sed s/;.*//g
第一个 sed 替换 fck=35 之前的所有内容; fck=35;本身什么也没有(删除它),第二个 sed 删除下一个分隔符之后的所有内容。
但听起来您还希望能够选择线上的特定列(fmd),因为您需要更多类似的东西:
grep -e "fck=35" | sed s/.*fmd=/fmd=/g | sed s/[;,].*//g
这将删除“fmd=”之前的所有元素,然后删除下一个分隔符(或逗号,似乎您需要处理它)之后的所有内容。