awk - 使用 grep / sed 用分号替换列表中的值,换行作为分隔符
问题描述
我是相当新的 grep、sed 和 awk。我过去曾使用它们来提取行和/或替换确切列表中的内容。
在这种情况下,我对如何去做感到困惑。我有两个 csv 文件。
我的第一个 csv 文件是由空格和分号分隔的名称。
姓名, 弗兰克 坦率; 约翰; 抢; , 约翰; 缺口; ,
第二个 csv 带有位置和名称
地点名称, 法国,弗兰克, 新泽西州约翰, 尼克,德国, 罗布,日本,
我希望输出将位置添加为名称旁边的列。
姓名、地点、 法兰克,法国, 坦率; 约翰; 抢; , 法国; 新泽西州; 日本, 约翰; 缺口; , 新泽西州; 德国,
如何逐行搜索第二个 csv 文件并将每个名称视为唯一名称以提取其各自的位置?然后输出它,这样它就可以用分号保留每行的信息..
我到目前为止所做的是:
猫文件1.csv | 切-f1 | tr';' '\t' > 文件-test.tsv
谢谢你。
解决方案
您的文件格式有些奇怪。逗号整体分隔,各个字段用分号分隔,但有时尾随分号有时不。此外,在编写此答案时,您的第二个文件仍然具有第一个数据行的“位置、名称”和所有其余部分的“名称、位置”。我假设每一行的实际文件都是“位置,名称”。
以下是我的处理方式:
- 通过第二个文件并创建从名称到位置的映射
- 通过第一个文件并应用映射
这是我的解决方案,仅使用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
=“正在处理的行数”。这从 1 开始并永远递增,无论有多少文件被处理awk
FNR
=“文件行号”。这从 1 开始,处理每个文件
所以当两者都为 1 时,正在处理映射文件的第一行。当FNR
为 1 但NR
大于 1 时,正在处理第二个文件。
还,
awk
*, *
可以使用正则表达式作为分隔符,所以我告诉它使用逗号作为分隔符( ),两边都有零个或多个空格。$0
= 整行$1
,$2
, 等是使用指定分隔符拆分时每行的各个字段。
其余的逻辑从脚本中的代码和注释中应该是不言而喻的。
按此顺序处理文件时
- file2.csv = 您的第二个文件,但在所有行上都有“位置、名称”顺序
- file1.csv = 你的第一个文件
输出是:
Name, Location,
Frank , France,
Frank; John; Rob; , France; New Jersey; Japan,
John; Nick; , New Jersey; Germany,
推荐阅读
- swift - 删除带有动画的行后更新表格视图的最佳方法?
- python - 完美数字代码的效率(Python)
- javascript - 如何阻止函数在 NodeJS 中过早运行?
- python - 这条线二维数组到一维数组的转换是如何工作的?
- docker-compose - 如何将 bazel 与 docker-compose 一起使用?
- laravel - 如何通过 Laravel 中的数据透视表从多个表中获取值?
- node.js - 在 Google Oauth2 登录后将 JWT 传递给 UI 应用程序
- php - 在批处理 PHP 文件中添加 2 个值
- c# - C# 空锁块是否被“优化”掉了?
- sql-server - PostgreSQL 中 SQL Server hierarchyid 的等效数据类型是什么