以下是我的文件内容,以下是我的要求 基于第1列和第5列的值,我想将第7列中的值替换为“1”。
例如:
输入文件:
Change|sinmg|1234|ewfew|def|fdfd|JAMES|rewr|ROBERT|3|fe
Change|sinmg|2345|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|
noChange|sinmg|2323|ewfew|def|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|fe
Change|sinmg|3456|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|
Change|sinmg|2345|ewfew|defererence|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|
上面只是一个示例,使其更容易解释。但是,我想从文件传递第1列和第5列的值以匹配文件中的值。如果它匹配,那么只用值“1”替换第7列,否则不要对行做任何事情,保持原样。
我尝试了几种选择,但未能达到所需的效果。
perl -F'\|' -i -lape 'if ($F[0] eq "change" && $F[4] eq "defer") { s/$F[6]/1/g;}' file_name
以上命令正在替换文件中3的所有值,而不考虑字段。但我想通过将不同的值传递给循环中的第1列和第4列,仅基于第1列和第4列替换第6列值。
添加更多信息:
正如我上面提到的,上面的例子只是我问题的最简单形式,让每个人都能理解这个要求。我有一个名为“listfile”的文件,其中包含第1列和第5列的值列表以进行匹配。如果源文件中第1列和第5列中的值与从文件“listfile”传递的值匹配,则解决方案应将第7列中的值替换为“1”。否则不要对源文件中的行执行任何操作,保持原样。
我尝试在下面做,但无法达到要求。
#!/usr/bin/ksh
for line in $(cat dir/listfile)
do
VAR1=$(echo $line | nawk -F"|" '{print $1}')
VAR2=$(echo $line | nawk -F"|" '{print $2}')
nawk -F"|" 'BEGIN {OFS="|"} {if($1!="'"$VAR1"'" && $5!="'"$VAR2"'") {$8="1"; print $0;} else {print $0;}}' dir/sourcefile >> dir/sourcefile_REVISED
done
替换No no 7后原始源文件和修订源文件之间的记录数不应相同。唯一的事情是文件列表文件中的第1列和第5列的所有值,我需要将第7列的值替换为“1”。
谢谢,
答案 0 :(得分:1)
您可以使用awk
执行此操作。
awk -F'|' 'BEGIN{OFS="|"}{if($1=="Change"&&$5=="defer"){$7=1}{print}}' file
我意识到你还需要第5列来匹配“不同”...以下应该有效:
awk -F'|' 'BEGIN{OFS="|"}{if($1=="Change"&&$5=="defer"||$5=="defererence"){$7=1}{print}}' file
答案 1 :(得分:1)
perl -F'\|' -i -lape '
BEGIN{ $" = "|" }
$F[6]=1, $_="@F" if $F[0] eq "Change" && $F[4] =~ /^defer(erence)?$/;
' listfile
答案 2 :(得分:0)
替换运算符s///
不理解数据列的概念,它只对给定的字符串进行操作。在这种情况下,由于g
修饰符,您将替换输入行中出现的第7列到处中的任何内容。
@imauser的答案中的awk
解决方案是一个很好的解决方案。
答案 3 :(得分:0)
使用awk
,您可以:
$ awk '$1=="Change"&&$5~/^defer(erence)?$/{$7=1}1' FS='|' OFS='|' file
Change|sinmg|1234|ewfew|def|fdfd|JAMES|rewr|ROBERT|3|fe
Change|sinmg|2345|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|1|rewr|BEAEY|3|
noChange|sinmg|2323|ewfew|def|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|fe
Change|sinmg|3456|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|1|rewr|BEAEY|3|
Change|sinmg|2345|ewfew|defererence|VENKTRAAAMMAMAMAMMAMA|1|rewr|BEAEY|
答案 4 :(得分:0)
在替换之前,您仍然可以通过“跳过”前六个字段来使用perl + regexp解决方案:
perl -F'\|' -i -lapE 'if ($F[0] eq "change" && $F[4] =~ m{^defer(erence)?$}) { s{^(?:[^|]*\|){6}\K([^|]*)}{1} }' file_name
优于awk解决方案的优势:您仍然可以在此使用-i
开关。
答案 5 :(得分:0)
您可以使用split
脚本中的join
和perl
完成此操作,如下所示:
#!/usr/bin/perl
use warnings;
use strict;
my $infile = "dir/sourcefile";
my $listfile = "dir/listfile";
my $outfile = "dir/sourcefile_REVISED";
my @list;
open LFOPEN, $listfile or die $!;
while (<LFOPEN>) {
chomp;
my @col = split /\|/, $_;
push @list, \@col;
}
close LFOPEN;
open IFOPEN, $infile or die $!;
open OFOPEN, '>', $outfile or die $!;
while (<IFOPEN>) {
chomp;
my @col = split /\|/, $_;
foreach my $lref (@list) {
$col[6] = '1' if ($col[0] eq $lref->[0] and $col[4] eq $lref->[1]);
}
print OFOPEN join ('|', @col) . "\n";
}
close IFOPEN;
close OFOPEN;
输入(dir / sourcefile):
Change|sinmg|1234|ewfew|def|fdfd|JAMES|rewr|ROBERT|3|fe
Change|sinmg|2345|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|
noChange|sinmg|2323|ewfew|def|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|fe
Change|sinmg|3456|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|
Change|sinmg|2345|ewfew|defererence|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|
列表(目录/列表文件):
Change|defer
Change|defererence
输出(dir / sourcefile_REVISED):
Change|sinmg|1234|ewfew|def|fdfd|JAMES|rewr|ROBERT|3|fe
Change|sinmg|2345|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|1|rewr|BEAEY|3
noChange|sinmg|2323|ewfew|def|VENKTRAAAMMAMAMAMMAMA|3|rewr|BEAEY|3|fe
Change|sinmg|3456|ewfew|defer|VENKTRAAAMMAMAMAMMAMA|1|rewr|BEAEY|3
Change|sinmg|2345|ewfew|defererence|VENKTRAAAMMAMAMAMMAMA|1|rewr|BEAEY|3