【问题标题】:Find value from one csv in another one (like vlookup) in bash (Linux)在 bash (Linux) 中从另一个 csv 中查找值(如 vlookup)
【发布时间】:2012-05-28 16:33:20
【问题描述】:

我已经尝试了所有在网上找到的方法来解决我的问题,但效果不佳。

基本上我有两个 csv 文件(管道分隔):

file1.csv:

123|21|0452|IE|IE|1|MAYOBAN|BRIN|OFFICE|STREET|MAIN STREET|MAYOBAN|

123|21|0453|IE|IE|1|CORKKIN|ROBERT|SURNAME|CORK|APTS|CORKKIN|

123|21|0452|IE|IE|1|CORKCOR|NAME|HARRINGTON|DUBLIN|STREET|CORKCOR|

file2.csv:

MAYOBAN|BANGOR|2400

MAYOBEL|BELLAVARY|2400

CORKKIN|KINSALE|2200

CORKCOR|CORK|2200

DUBLD11|DUBLIN 11|2100

我需要一个 linux bash 脚本来根据 file1 中 pos7 的内容从 file2 中找到 pos.3 的值。

例子:

file1, line1, pos 7: MAYOBAN
find MAYOBAN in file2, return pos 3 (2400)

输出应该是这样的:

**2400**

**2200**

**2200**

**etc...**

请帮忙 杰克

【问题讨论】:

  • 拆分成数组并检查是否有重复。不确定这是不是这样,但这是我的第一个想法。

标签: linux bash csv compare vlookup


【解决方案1】:

您可以使用米勒 (https://github.com/johnkerl/miller)。

从input01.txt开始

123|21|0452|IE|IE|1|MAYOBAN|BRIN|OFFICE|STREET|MAIN STREET|MAYOBAN|
123|21|0453|IE|IE|1|CORKKIN|ROBERT|SURNAME|CORK|APTS|CORKKIN|
123|21|0452|IE|IE|1|CORKCOR|NAME|HARRINGTON|DUBLIN|STREET|CORKCOR|

和 input02.txt

MAYOBAN|BANGOR|2400
MAYOBEL|BELLAVARY|2400
CORKKIN|KINSALE|2200
CORKCOR|CORK|2200
DUBLD11|DUBLIN 11|2100

正在运行

mlr --csv -N --ifs "|" join  -j 7 -l 7 -r 1 -f input01.txt then cut -f 3 input02.txt

你会有

2400
2200
2200

一些注意事项:

  • -N设置输入输出不带header;
  • --ifs "|" 设置输入字段分隔符;
  • -l 7 -r 1 设置输入文件的连接字段;
  • cut -f 3 从连接输出中提取名为 3 的字段

【讨论】:

    【解决方案2】:
    cut -d\| -f7 file1.csv|while read line
    do 
      grep $line file1.csv|cut -d\| -f3
    done
    

    【讨论】:

      【解决方案3】:

      这会起作用,但是由于必须对输入文件进行排序,因此会影响输出顺序:

      join -t '|' -1 7 -2 1 -o 2.3 <(sort -t '|' -k7,7 file1.csv) <(sort -t '|' -k1,1 file2.csv)
      

      输出如下:

      2200
      2200
      2400
      

      这是没用的。为了获得有用的输出,请包含键值:

      join -t '|' -1 7 -2 1 -o 0,2.3 <(sort -t '|' -k7,7 file1.csv) <(sort -t '|' -k1,1 file2.csv)
      

      然后输出如下所示:

      CORKCOR|2200
      CORKKIN|2200
      MAYOBAN|2400
      

      编辑:

      这是一个 AWK 版本:

      awk -F '|' 'FNR == NR {keys[$7]; next} {if ($1 in keys) print $3}' file1.csv file2.csv
      

      这循环通过 file1.csv 并为字段 7 的每个值创建数组条目。只需引用一个数组元素即可创建它(具有空值)。 FNR 是当前文件中的记录号,NR 是所有文件中的记录号。当它们相等时,正在处理第一个文件。 next 指令读取下一条记录,创建一个循环。当FNR == NR 不再为真时,将处理后续文件。

      所以现在处理 file2.csv,如果它的字段 1 存在于数组中,则打印其字段 3。

      【讨论】:

      • 太棒了!这就像一个魅力。实际上第一个选项很好,因为我不需要排序。输出用于统计目的,所以如果数量没问题,那没关系。我尝试过 AWK,但效果不佳。
      • @Yasapl:我在答案中添加了 AWK 版本。如果您觉得我的回答有用,请将其标记为已接受并点赞。谢谢。
      【解决方案4】:

      一点点的接近,远离完美:

      DELIMITER="|"
      
      for i in $(cut -f 7 -d "${DELIMITER}" file1.csv ); 
      do 
          grep "${i}" file2.csv | cut -f 3 -d "${DELIMITER}"; 
      done
      

      【讨论】:

      • 来自Wikipedia:“每条记录由字段组成,由其他字符或字符串分隔,最常见的是文字逗号或制表符。”和“在通常的用法中,几乎所有以分隔符分隔的文本数据都可以称为 'CSV' 文件。”
      • @DennisWilliamson:谢谢你的启发。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-22
      • 1970-01-01
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      相关资源
      最近更新 更多