awk加入脚本让我非常兴奋

awk加入脚本让我非常兴奋,awk,Awk,我试图使用awk从第一个CSV文件“map.txt”中查找两列(col1=key,col2=value)的值,然后在用文件1的col2替换相同的col3时,使用第二个文件“textile.txt”的col3作为键 示例文件: map.txt a,apple b,pear c,peeps d,gingersnaps e,goop 1,This is one,a 2,This is two,b 3,This is three,c 4,This is four,d 5,This is five,e

我试图使用awk从第一个CSV文件“map.txt”中查找两列(col1=key,col2=value)的值,然后在用文件1的col2替换相同的col3时,使用第二个文件“textile.txt”的col3作为键

示例文件:

map.txt

a,apple
b,pear
c,peeps
d,gingersnaps
e,goop
1,This is one,a
2,This is two,b
3,This is three,c
4,This is four,d
5,This is five,e
textfile.txt

a,apple
b,pear
c,peeps
d,gingersnaps
e,goop
1,This is one,a
2,This is two,b
3,This is three,c
4,This is four,d
5,This is five,e
以及所需的输出:

1,This is one,apple
2,This is two,pear
3,This is three,peeps
4,This is four,gingersnaps
5,This is five,goop
结果: 我已经对测试文件进行了这项工作,但是当使用实际文件时,尽管密钥被正确地读入数组,但实际上只有一行,最后一行(如果存在多行)被正确地替换

已尝试各种版本的awk脚本--当前版本比较详细,并使用getline进行调试:

#!/usr/bin/awk -f

BEGIN{FS=OFS=","}

(FNR==NR){
fname=ARGV[ARGC-2];
print fname;
do
{getline < fname;
lookup[$1]=$2;
print $1 " = " $2;
}
while (getline);
close(fname)
fname=ARGV[ARGC-1];
}

(fname==ARGV[ARGC-1]){
print fname;
do
{getline < ARGV[ARGC-1];
$3=lookup[$3];
print $3 " " $0;
}
while (getline);
next;
} 
#/usr/bin/awk-f
开始{FS=OFS=“,”}
(FNR==NR){
fname=ARGV[ARGC-2];
打印fname;
做
{getline

值得一提的是,这在OSX上。

我认为你把它弄得太复杂了。 这似乎有效:

#!/usr/bin/awk -f

BEGIN {
    FS=OFS=","
}

NR == FNR {
    lookup[$1] = $2
}

NR != FNR {
    print $1,$2,lookup[$3]
}
运行这个,我得到:

# ./thing.awk map.txt textfile.txt
1,This is one,apple
2,This is two,pear
3,This is three,peeps
4,This is four,gingersnaps
5,This is five,goop

第一个块
NR==FNR{..}
读取映射文件。第二个是
textfile.txt
(以及您放在命令行上的任何其他文件)。

我认为您把它弄得太复杂了。 这似乎有效:

#!/usr/bin/awk -f

BEGIN {
    FS=OFS=","
}

NR == FNR {
    lookup[$1] = $2
}

NR != FNR {
    print $1,$2,lookup[$3]
}
运行这个,我得到:

# ./thing.awk map.txt textfile.txt
1,This is one,apple
2,This is two,pear
3,This is three,peeps
4,This is four,gingersnaps
5,This is five,goop

第一个块
NR==FNR{..}
读取映射文件。第二个脚本读取
textfile.txt
(以及您放在命令行上的任何其他文件)。

以下脚本避免了必须测试NR==FNR的(可能很小)开销,并使指定要翻译的字段的列号变得容易(此处:col=3):

awk-F,-v col=3-v dict=map.txt'
BEGIN{OFS=FS;while((getline 0){a[$1]=$2}
a[$col]{$col=a[$col]}
{打印$0}
'textfile.txt

请注意,如果在字典中找不到数据文件(textfile.txt)中某行的“键”,则上述脚本将打印该行而不进行更改。如果这不是所需的行为,则可以轻松调整脚本。

以下脚本避免了(可能很小)必须测试NR==FNR的开销,并使指定要转换的字段的列号变得容易(此处:col=3):

awk-F,-v col=3-v dict=map.txt'
BEGIN{OFS=FS;while((getline 0){a[$1]=$2}
a[$col]{$col=a[$col]}
{打印$0}
'textfile.txt


请注意,如果数据文件(textfile.txt)中某行的“键”如果在字典中找不到,则上面的脚本将打印该行而不进行更改。如果这不是所需的行为,则可以轻松调整脚本。

能否向我们显示用于调用awk脚本的命令行?如果您有权加入:
join-t,-1 1-2 3-o 2.1,2.2,1.2 map.txt textfile.txt
有OCCA使用
getline
,但不是很多。听起来您的真实数据有DOS行结尾或其他一些文本文件完整性问题(在OSX上,甚至可能有传统的MacOS行结尾,尽管我认为您不能再运行产生这些行结尾的软件)。有关疑难解答的提示,请参阅。tripleee--您先生或夫人是圣人。不知何故,在导出过程中,第一个文件最终使用了正确的UNIX LFs,但第二个文件最终使用了Windows CRLFs。我知道这是一个文件差异,但无法确定,因为在使用TextMate或TextWrangler的Mac环境中,我没有看到非常复杂的问题下图显示了EOL的不一致性。非常感谢您的敏锐观察。您可以向我们展示您用于调用awk脚本的命令行吗?如果您有权加入:
join-t,-1 1-2 3-o 2.1,2.2,1.2 map.txt textfile.txt
可以使用
getline
,但它们并不多。听起来您的真实数据已经被删除了DOS行尾或其他一些文本文件完整性问题(在OSX上,甚至可能有遗留的MacOS行尾,尽管我认为您不能再运行产生这些行尾的软件)。有关疑难解答的提示,请参阅。tripleee--您先生或夫人是圣人。不知何故,在导出过程中,第一个文件最终使用了正确的UNIX LFs,但第二个文件最终使用了Windows CRLFs。我知道这是一个文件差异,但无法确定,因为在使用TextMate或TextWrangler的Mac环境中,我没有看到非常复杂的问题底部查看EOL不一致。非常感谢您的敏锐观察。同意“使其过于复杂”的评估-您的解决方案非常符合要求。对于第一个文件,在块中使用
next
,这是非常常见的,因此对于第二个文件,您不需要
NR!=FNR
条件。@TomFenech正确。在第一个块中使用
next
,在第二个块之前消除否定条件,这是正确的解决方案,只要两个文件中出现相同的键。如果没有,则可能需要进行更多的工作,但OP尚未向我们展示如何处理。同意“使其过于复杂”的评估-您的解决方案正是所需要的。在第一个文件块中使用
next
是很常见的,因此第二个文件不需要
NR!=FNR
条件。@TomFenech是正确的。在第一个文件块中使用
next
并在第二个文件块之前去掉否定条件,这是正确的解决方案,只要两个文件中出现相同的键。如果它们没有出现,则可能需要进行更多的工作,但OP尚未向我们展示如何处理该问题。
NR==FNR
是一种标准模式;我真的不认为您的方法有任何优势。我不确定您为什么认为使用
getline
读取一行会有任何问题这比简单的比较要复杂得多。这与开销无关,而是与事实有关