我有文件1:
col1=val1|col2=val2|col3=val3|col4=val4
col1=val1|col2=val2|col4=val4|col5=val5|col6=val6
col1=val1|col3=val3|col4=val4|col6=val6
col1=val1|col2=val2|col3=val3|col4=val4|col5=val5|col6=val6
以及 file2 中的唯一列列表:
col1
col2
col3
col4
col5
col6
根据 file2 列序列,我需要使用管道分隔符从单独文件中的 file1 获取其值。
输出看起来像:
val1|val2|val3|val4|||
val1|val2||val4|val5|val6
val1||val3|val4||val6
val1|val2|val3|val4|val5|val6
答案1
每当您输入具有名称=值对的数据时,最好的方法是首先创建一个名称->值数组,然后通过其命名索引打印该数组的内容。在这种情况下,这些名称的顺序来自不同的文件,因此只需先阅读该文件:
$ cat tst.awk
BEGIN { FS="[=|]"; OFS="|" }
NR==FNR { outFldNames[++numOutFlds]=$0; next }
{
delete name2val
for (inFldNr=1; inFldNr<NF; inFldNr++) {
name2val[$inFldNr] = $(inFldNr+1)
}
for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
printf "%s%s", name2val[outFldNames[outFldNr]], (outFldNr<numOutFlds ? OFS : ORS)
}
}
$ awk -f tst.awk file2 file1
val1|val2|val3|val4||
val1|val2||val4|val5|val6
val1||val3|val4||val6
val1|val2|val3|val4|val5|val6
答案2
perl -wMstrict -Mvars='*A' -lne '
if ( @ARGV ) { push @A, $_; }
else {
my %h = /([^|=]+)=([^|]+)/g;
$,="|"; print map { $h{$_} // (($_ eq $A[-1]) ? q/|/ : q//) } @A;
}
' file2 file1
注意第一行输出: 这里有 3 个管道。因此,map
逻辑就是这样的。
输出
val1|val2|val3|val4|||
val1|val2||val4|val5|val6
val1||val3|val4||val6
val1|val2|val3|val4|val5|val6
答案3
$ cat file1
col1=val1|col2=val2|col3=val3|col4=val4
col1=val1|col2=val2|col4=val4|col5=val5|col6=val6
col1=val1|col3=val3|col4=val4|col6=val6
col1=val1|col2=val2|col3=val3|col4=val4|col5=val5|col6=val6
我更改了 file2 以证明省略了 file2 中未列出的列:
$ cat file2
col1
col2
col4
col5
col6
剧本:
#!/bin/bash
patterns="$(tr '\n' '|' < file2| sed 's/|$//')"
awk -F'|' -v pat="$patterns" '{
o=0
for (i=1; i<=6; i++) {
f=i-o
split($f,a,"=")
if ( a[1] ~ i ) {
if ( a[1] ~ pat ) {
printf "%s", a[2]
}
if (i != 6) {printf "|"}
} else {
printf "|"
o++
}
}
printf "\n"
}' file1
没有 col3 值的输出:
$ ./script
val1|val2||val4|||
val1|val2||val4|val5|val6
val1|||val4||val6
val1|val2||val4|val5|val6
答案4
这是使用 awk 和手动映射的经典编程方法:
$ awk -F"[=|]" 'NR==FNR{header[++c]=$1;next}\
{
record="";
for (h=1;h<=c;h++)
{
found="*";
for (field=1;field<=NF;field+=2) \
{
if ($field==header[h])
{found=$(field+1);break}
};
record=record "|" found;
}
print record
}' file2 file1
#Output:
|val1|val2|val3|val4|*|*
|val1|val2|*|val4|val5|val6
|val1|*|val3|val4|*|val6
|val1|val2|val3|val4|val5|val6
对于不同的 file2 - 不同的列顺序如
col6
col4
col3
col5
col2
col1
输出将相应地遵循:
|*|val4|val3|*|val2|val1
|val6|val4|*|val5|val2|val1
|val6|val4|val3|*|*|val1
|val6|val4|val3|val5|val2|val1