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
- 将输入字段分隔符设置为
代码>
- 运行查找文件,创建一个数组
,其中键位于第1列,并将第2列存储为值a
- 在内存中加载查找文件后,用数组值替换数据文件的第二列
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非常强大,但这是非常小的代码。伟大的