Awk 合并具有不同列和行的文件
我有一些文件,我需要加入,我已经寻找了一些解决方案,但他们不适合我需要的,我有以下文件 a、 csv 日期| A | B | C | DAwk 合并具有不同列和行的文件,awk,Awk,我有一些文件,我需要加入,我已经寻找了一些解决方案,但他们不适合我需要的,我有以下文件 a、 csv 日期| A | B | C | D 2017年3月15日| 1 | 3 | 9 | 4 及 b、 csv 日期| A | C | D | E 2017年3月16日| 2 | 9 | 3 | 4 我想得到下一个输出: 日期| A | B | C | D | E 2017年3月15日| 1 | 3 | 9 | 4 | 0 2017年3月16日| 2 | 0 | 9 | 3 | 4 任何见解或建议都将
2017年3月15日| 1 | 3 | 9 | 4 及 b、 csv 日期| A | C | D | E
2017年3月16日| 2 | 9 | 3 | 4 我想得到下一个输出: 日期| A | B | C | D | E
2017年3月15日| 1 | 3 | 9 | 4 | 0
2017年3月16日| 2 | 0 | 9 | 3 | 4 任何见解或建议都将不胜感激 编辑: 谢谢大家 这些文件示例并不总是相同的 有时它可能有10到50列,1到30行(日期)类似这样的内容
awk 'BEGIN {FS=OFS="|"}
FNR==1 {split($0,h); next}
{c++;
for(i=1;i<=NF;i++)
{a[h[i],c]=$i;
hall[h[i]]}}
END {for(k in hall) printf "%s", k OFS;
print "";
for(i=1;i<=c;i++)
{for(k in hall) printf "%s", ((k,i) in a?a[k,i]:0) OFS;
print ""}}' file1 file2
A|B|C|D|E|date |
1|3|9|4|0|15-03-2017|
2|0|9|3|4|16-03-2017|
awk'BEGIN{FS=OFS=“|”}
FNR==1{split($0,h);next}
{c++;
对于(i=1;i类似的东西
awk 'BEGIN {FS=OFS="|"}
FNR==1 {split($0,h); next}
{c++;
for(i=1;i<=NF;i++)
{a[h[i],c]=$i;
hall[h[i]]}}
END {for(k in hall) printf "%s", k OFS;
print "";
for(i=1;i<=c;i++)
{for(k in hall) printf "%s", ((k,i) in a?a[k,i]:0) OFS;
print ""}}' file1 file2
A|B|C|D|E|date |
1|3|9|4|0|15-03-2017|
2|0|9|3|4|16-03-2017|
awk'BEGIN{FS=OFS=“|”}
FNR==1{split($0,h);next}
{c++;
对于(i=1;i使用sed的稍微简单的解决方案
:
sed 's/$/|0/;1s/0/E/' a.csv; sed '1d;s/|/|0|/2' b.csv
使用sed
的稍微简单的解决方案:
sed 's/$/|0/;1s/0/E/' a.csv; sed '1d;s/|/|0|/2' b.csv
为了可读性,我将答案扩展为一个脚本。您可以使用带有awk-f
选项的脚本。从BEGIN
语句开始:指定
作为字段分隔符,使用关联数组将索引映射到每个标题标签,并打印完整的标题。对于每个文件,将标签映射到第1行的索引n将标签映射到第2行的数据,并将空数据字段替换为“0”。打印已填写的行并清除下一个文件的数组
BEGIN{
# field separator
FS="|"
# index:label mapping
map[1]="date "; map[2]="A"; map[3]="B"
map[4]="C"; map[5]="D"; map[6]="E"
# print full header
print "date |A|B|C|D|E"
}
# first line of each file, create index:label mapping
FNR==1{
for (i=1;i<=NF;i++)
label[i]=$i
}
# next line of the file, create label:data mapping
FNR==2{
for (i=1;i<=NF;i++)
data[label[i]]=$i
# cycle through index:label mapping and print data
# for each label or "0" if there is no data
printf("%s", data["date "])
for (i=2;i<=6;i++) {
(data[map[i]]) ? s=data[map[i]] : s=0
printf("|%s", s)
}
print "" # print empty string for newline
# delete arrays to start from scratch on the following file
delete label
delete data
}
为了可读性,我将答案扩展为一个脚本。您可以使用带有awk-f
选项的脚本。从BEGIN
语句开始:指定
作为字段分隔符,使用关联数组将索引映射到每个标题标签,并打印完整的标题。对于每个文件,将标签映射到第1行的索引n将标签映射到第2行的数据,并将空数据字段替换为“0”。打印已填写的行并清除下一个文件的数组
BEGIN{
# field separator
FS="|"
# index:label mapping
map[1]="date "; map[2]="A"; map[3]="B"
map[4]="C"; map[5]="D"; map[6]="E"
# print full header
print "date |A|B|C|D|E"
}
# first line of each file, create index:label mapping
FNR==1{
for (i=1;i<=NF;i++)
label[i]=$i
}
# next line of the file, create label:data mapping
FNR==2{
for (i=1;i<=NF;i++)
data[label[i]]=$i
# cycle through index:label mapping and print data
# for each label or "0" if there is no data
printf("%s", data["date "])
for (i=2;i<=6;i++) {
(data[map[i]]) ? s=data[map[i]] : s=0
printf("|%s", s)
}
print "" # print empty string for newline
# delete arrays to start from scratch on the following file
delete label
delete data
}
我解决了这个问题
我改变了获取数据的方式
大概是这样的:
today=$(date +%Y%m%d)
echo "DataBase "$(date +%d/%m/%Y)>/jdb"$today".txt
du -s $(ls -l|grep ^d|awk '{print $9})|awk '{print $2" "$1" "}'>>/jdb"$today".txt
输出如下所示:
jdb_20170507.txt:
database 07/05/2017
jdb_A 4345
jdb_CFX 7654
jdb_ZZXD 97865
jdb_20170508.txt:
database 08/05/2017
jdb_A 9876
jdb_CFX 7545
jdb_ZXCFG 2344
为此,jdb_20170508.txt中的示例删除了jdb_ZZXD数据库,并创建了jdb_ZXCFG数据库
使用此结构,我可以使用JOIN命令:
x=0
touch jdbaux$x.txt
for jdbfile in $(ls -1t|grep jdb2)
do
y=$(($x+1))
join -a1 -a2 -e0 -o auto --nocheck-order jdbaux$x.txt $jdbfile >jdbaux$y.txt
rm jdbaux$x.txt
x=$(($x+1))
done
这是本月所有档案的递归联接乡村选项
-a1=文件一
-a2=文件二
-e0=用0替换缺少的输入字段
-o自动=输出自动格式
--nocheck order=不检查输入是否正确排序
输出如下所示:
jdb_sizes201705.txt:
database 07/05/2017 08/05/2017
jdb_A 4345 9876
jdb_CFX 7654 7545
jdb_ZZXD 97865 0
jdb_ZXCFG 0 2344
最后一步是枢轴
cat jdb_sizes201705.txt |awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}'
我知道这不是最好的解决方案,但它很有效
谢谢!我解决了这个问题
我改变了获取数据的方式
大概是这样的:
today=$(date +%Y%m%d)
echo "DataBase "$(date +%d/%m/%Y)>/jdb"$today".txt
du -s $(ls -l|grep ^d|awk '{print $9})|awk '{print $2" "$1" "}'>>/jdb"$today".txt
输出如下所示:
jdb_20170507.txt:
database 07/05/2017
jdb_A 4345
jdb_CFX 7654
jdb_ZZXD 97865
jdb_20170508.txt:
database 08/05/2017
jdb_A 9876
jdb_CFX 7545
jdb_ZXCFG 2344
为此,jdb_20170508.txt中的示例删除了jdb_ZZXD数据库,并创建了jdb_ZXCFG数据库
使用此结构,我可以使用JOIN命令:
x=0
touch jdbaux$x.txt
for jdbfile in $(ls -1t|grep jdb2)
do
y=$(($x+1))
join -a1 -a2 -e0 -o auto --nocheck-order jdbaux$x.txt $jdbfile >jdbaux$y.txt
rm jdbaux$x.txt
x=$(($x+1))
done
这是本月所有档案的递归联接乡村选项
-a1=文件一
-a2=文件二
-e0=用0替换缺少的输入字段
-o自动=输出自动格式
--nocheck order=不检查输入是否正确排序
输出如下所示:
jdb_sizes201705.txt:
database 07/05/2017 08/05/2017
jdb_A 4345 9876
jdb_CFX 7654 7545
jdb_ZZXD 97865 0
jdb_ZXCFG 0 2344
最后一步是枢轴
cat jdb_sizes201705.txt |awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}'
我知道这不是最好的解决方案,但它很有效
谢谢!有趣的任务,初始文件可以有多行(两行以上)?这不是join
的任务。请删除标签。有趣的任务,初始文件可以有多行(两行以上)?这不是join
的任务。请删除标签。OMG,为我的疏忽道歉(删除答案)谢谢,我为我的疏忽道歉(已删除的答案)。谢谢