Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash Shell脚本-文件中的智能替换与第二个文件中的查找_Bash_Shell_Awk - Fatal编程技术网

Bash Shell脚本-文件中的智能替换与第二个文件中的查找

Bash Shell脚本-文件中的智能替换与第二个文件中的查找,bash,shell,awk,Bash,Shell,Awk,我有两个文件,一个数据文件和一个查找文件 数据文件的一个字段必须由一个值更改,该值可以在查找文件中找到 数据文件如下所示: 2013-04-24;1;0.1635;1.4135 2013-04-24;1;0.9135;1.4135 2013-04-24;2;0.9135;1.4135 1;2ab1e4c0-de4d-11e2-a934-0f0479162b1b 2;2ab21e90-de4d-11e2-9ce8-d368d9512bad 3;2ab2582e-de4d-11e2-bb5f-6b

我有两个文件,一个数据文件和一个查找文件

数据文件的一个字段必须由一个值更改,该值可以在查找文件中找到

数据文件如下所示:

2013-04-24;1;0.1635;1.4135
2013-04-24;1;0.9135;1.4135
2013-04-24;2;0.9135;1.4135
1;2ab1e4c0-de4d-11e2-a934-0f0479162b1b
2;2ab21e90-de4d-11e2-9ce8-d368d9512bad
3;2ab2582e-de4d-11e2-bb5f-6b1f6c4437f8
查找文件如下所示:

2013-04-24;1;0.1635;1.4135
2013-04-24;1;0.9135;1.4135
2013-04-24;2;0.9135;1.4135
1;2ab1e4c0-de4d-11e2-a934-0f0479162b1b
2;2ab21e90-de4d-11e2-9ce8-d368d9512bad
3;2ab2582e-de4d-11e2-bb5f-6b1f6c4437f8
结果必须是:

2013-04-24 2ab1e4c0-de4d-11e2-a934-0f0479162b1b 0.1635 1.4135
2013-04-24 2ab1e4c0-de4d-11e2-a934-0f0479162b1b 0.9135 1.4135
2013-04-24 2ab21e90-de4d-11e2-9ce8-d368d9512bad 0.9135 1.4135
我知道如何使用awk读取数据文件并转换字段分隔符

    awk 'BEGIN { FS = ";"; OFS = " " } ;
        {  print $1, $2, #3, $4 }' $1 > $1.updated
但我不知道在shell脚本的查找文件中查找变量$2并用UUID替换原始值的聪明方法

查找文件永远不会很大,在极端情况下最多会有1000条记录


任何使用bash或perl的解决方案都将不胜感激

这应该适合您:

awk -F';' 'NR==FNR{a[$1]=$2;next}{$2=a[$2]}1' lookup data
  • 将输入字段分隔符设置为
  • 运行查找文件,创建一个数组
    a
    ,其中键位于第1列,并将第2列存储为值
  • 在内存中加载查找文件后,用数组值替换数据文件的第二列
    • awk
      有“数组”(实际上它的功能类似于散列/字典),可以很好地实现这一点

      awk 'BEGIN { FS = ";"; OFS = " " }
           {
               if (NR == FNR)
                   values[$1] = $2
               else
                   print $1, values[$2], $3, $4
           }' lookup data
      

      这就是
      join
      的作用,尽管它确实要求在要匹配的字段上对两个输入文件进行排序:

      sort -t\; -k2,2 datafile.txt > datafile.tmp
      sort -t\; -k1,1 lookup.txt > lookup.tmp
      join -t\; -1 2 -2 1 -o 1.1,2.2,1.3,1.4 datafile.tmp lookup.tmp | tr ';' ' '
      
      如果您使用的是
      bash
      ,则可以将所有内容合并到一行中,并跳过临时文件:

      join -t\; -1 2 -2 1 -o 1.1,2.2,1.3,1.4 <(sort -t\; -k2,2 datafile.txt) <(sort -t\; -k1,1 lookup.txt) | tr ';' ' '
      

      join-t\-12-21-o1.1,2.2,1.3,1.4您可以使用全Bash解决方案

      while IFS=\; read _ stored; do
          string+=($stored)
      done < lookup_file
      ref=0
      while IFS=\; read date _ data1 data2; do
          echo $date ${string[$ref]} $data1 $data2
          ((ref++))
      done < data_file
      
      而IFS=\;读存储;做
      字符串+=($已存储)
      完成

      这将查找文件中的目标字符串存储在数组中,并在从数据文件读取时引用它们。

      仅供参考,您的结果不正确。您的数据文件将
      2
      作为第三行,该行由查找文件中的
      3
      值替换。您是对的。为了不让更多的读者感到困惑,我编辑了这篇文章。在软件中,测试一个条件(例如,
      NR==FNR
      )然后测试同一条件的否定(
      NR!=FNR
      )是一种不好的做法。只需使用
      next
      ,或者,在这种情况下,最好使用if-else编码;仅仅因为它是
      awk
      并不意味着你应该忽略最佳实践。我按照你的建议编辑了代码。(我使用了if-else,因为已经有了一个带有
      next
      的答案,而且对于
      awk
      新手来说,条件答案可能更容易理解。)谢谢!这很有帮助。我知道awk非常强大,但这是非常小的代码。伟大的