您的文件格式有些奇怪。逗号整体分隔,各个字段用分号分隔,但有时尾随分号有时不。
此外,在编写此答案时,您的第二个文件仍然具有第一个数据行的“位置、名称”和所有其余部分的“名称、位置”。我假设 actual 文件的每一行都是“位置,名称”。
这是我的处理方式:
- 通过第二个文件并创建从名称到位置的映射
- 通过第一个文件并应用映射
这是我的解决方案,只使用 awk:
# use delimiter of zero or more spaces on either side of a comma
awk -F ' *, *' '
# First line of first file processed; set flag variable
FNR == 1 && NR == 1 {mapfile = 1;}
# Lines 2+ in the map file: save the mapping
mapfile && FNR > 1 {map[$2] = $1;}
# First line of second file; print header and reset flag
FNR == 1 && NR > 1 {print "Name, Location,"; mapfile = 0;}
# Process lines 2+ in the name file (i.e. not the map file)
!mapfile && FNR > 1 {
data = $0;
sub(/ *, *$/,"",data); # remove trailing comma
sub(/ *; *$/,"",data); # remove trailing semicolon
# create "names" array of length "num"
num = split(data,names,/ *; */);
locs = ""; # init location string to empty
for (i = 1; i <= num; i++)
{
locs = locs map[names[i]] "; ";
}
sub(/; $/,",",locs); # change last semicolon to comma
# print original line from name file, and append locations
print $0 " " locs;
}' file2.csv file1.csv
更多解释:
-
NR = 正在处理“行数”。无论awk 处理了多少文件,它都从 1 开始并永远递增
-
FNR = "文件行号"。这从 1 开始,每个文件都在处理中
所以当两者都为 1 时,正在处理映射文件的第一行。
当FNR 为1 但NR 大于1 时,正在处理第二个文件。
还有,
-
awk 可以使用正则表达式作为分隔符,所以我告诉它使用逗号作为分隔符,两边各有零个或多个空格 ( *, *)。
-
$0 = 整行
-
$1、$2 等是使用指定分隔符拆分时每行的各个字段。
其余的逻辑从脚本中的代码和cmets应该是不言而喻的。
按此顺序处理文件时
- file2.csv = 您的第二个文件,但在所有行中使用“位置、名称”顺序
- file1.csv = 您的第一个文件
输出是:
Name, Location,
Frank , France,
Frank; John; Rob; , France; New Jersey; Japan,
John; Nick; , New Jersey; Germany,