首页 > 解决方案 > 使用 grep / sed 用分号替换列表中的值,换行作为分隔符

问题描述

我是相当新的 grep、sed 和 awk。我过去曾使用它们来提取行和/或替换确切列表中的内容。

在这种情况下,我对如何去做感到困惑。我有两个 csv 文件。

我的第一个 csv 文件是由空格和分号分隔的名称。

姓名,
弗兰克
坦率; 约翰; 抢; ,
约翰; 缺口; ,

第二个 csv 带有位置和名称

地点名称,
法国,弗兰克,
新泽西州约翰,
尼克,德国,
罗布,日本,

我希望输出将位置添加为名称旁边的列。

姓名、地点、
法兰克,法国,
坦率; 约翰; 抢; , 法国; 新泽西州; 日本,
约翰; 缺口; , 新泽西州; 德国,

如何逐行搜索第二个 csv 文件并将每个名称视为唯一名称以提取其各自的位置?然后输出它,这样它就可以用分号保留每行的信息..

我到目前为止所做的是:

猫文件1.csv | 切-f1 | tr';' '\t' > 文件-test.tsv

谢谢你。

标签: awksedgrep

解决方案


您的文件格式有些奇怪。逗号整体分隔,各个字段用分号分隔,但有时尾随分号有时不。此外,在编写此答案时,您的第二个文件仍然具有第一个数据行的“位置、名称”和所有其余部分的“名称、位置”。我假设每一行的实际文件都是“位置,名称”。

以下是我的处理方式:

  • 通过第二个文件并创建从名称到位置的映射
  • 通过第一个文件并应用映射

这是我的解决方案,仅使用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, 等是使用指定分隔符拆分时每行的各个字段。

其余的逻辑从脚本中的代码和注释中应该是不言而喻的。

按此顺序处理文件时

  1. file2.csv = 您的第二个文件,但在所有行上都有“位置、名称”顺序
  2. file1.csv = 你的第一个文件

输出是:

Name, Location,
Frank , France,
Frank; John; Rob;  , France; New Jersey; Japan,
John; Nick;  , New Jersey; Germany,

推荐阅读