AWK:遍历文件两次,执行不同的任务
AWK: go through the file twice, doing different tasks
我正在处理相当大的推文集合,如果提到的用户也在文件:
users = new Dictionary()
for each line in file:
username = get_username(line)
userid = get_userid(line)
users.add(key = userid, value = username)
for each line in file:
mentioned_names = get_mentioned_names(line)
mentioned_ids = mentioned_names.map(x => if x in users: users[x] else null)
print "$line | $mentioned_ids"
我已经在使用 GAWK 处理该文件,因此我决定尝试将其添加到我的 AWK 脚本中,而不是在 Python 或 C 中再次处理它。但是,我找不到一种方法来传递同一个文件,为每个文件执行不同的代码。大多数解决方案都意味着多次调用 AWK,但随后我会丢失在第一遍中创建的关联数组。
我可以用非常 hacky 的方式来做到这一点(比如 cat
文件两次,通过 sed
传递给每个 cat
中的所有行添加不同的前缀), 但我希望能够在几个月内理解这段代码而不讨厌自己。
执行此操作的 AWK 方法是什么?
PD:
我发现的不太糟糕的方法:
function rewind( i)
{
# from https://www.gnu.org/software/gawk/manual/html_node/Rewind-Function.html
# shift remaining arguments up
for (i = ARGC; i > ARGIND; i--)
ARGV[i] = ARGV[i-1]
# make sure gawk knows to keep going
ARGC++
# make current file next to get done
ARGV[ARGIND+1] = FILENAME
# do it
nextfile
}
BEGIN {
count = 1;
}
count == 1 {
# first pass, fills an associative array
}
count == 2 {
# second pass, uses the array
}
FNR == 30 {
# handcoded length, horrible
# could also be automated calling wc -l, passing as parameter
if (count == 1) {
count = 2;
rewind(1)
}
}
在 awk 中处理两个单独的文件或同一个文件两次的惯用方法是这样的:
awk 'NR==FNR{
# fill associative array
next
}
{
# use the array
}' file1 file2
总记录数NR
只等于当前文件在第一个文件上的记录数FNR
。 next
跳过第一个文件的第二个块。然后为第二个文件处理第二个块。如果 file1
和 file2
是同一个文件,那么这将通过文件两次。
我正在处理相当大的推文集合,如果提到的用户也在文件:
users = new Dictionary()
for each line in file:
username = get_username(line)
userid = get_userid(line)
users.add(key = userid, value = username)
for each line in file:
mentioned_names = get_mentioned_names(line)
mentioned_ids = mentioned_names.map(x => if x in users: users[x] else null)
print "$line | $mentioned_ids"
我已经在使用 GAWK 处理该文件,因此我决定尝试将其添加到我的 AWK 脚本中,而不是在 Python 或 C 中再次处理它。但是,我找不到一种方法来传递同一个文件,为每个文件执行不同的代码。大多数解决方案都意味着多次调用 AWK,但随后我会丢失在第一遍中创建的关联数组。
我可以用非常 hacky 的方式来做到这一点(比如 cat
文件两次,通过 sed
传递给每个 cat
中的所有行添加不同的前缀), 但我希望能够在几个月内理解这段代码而不讨厌自己。
执行此操作的 AWK 方法是什么?
PD:
我发现的不太糟糕的方法:
function rewind( i)
{
# from https://www.gnu.org/software/gawk/manual/html_node/Rewind-Function.html
# shift remaining arguments up
for (i = ARGC; i > ARGIND; i--)
ARGV[i] = ARGV[i-1]
# make sure gawk knows to keep going
ARGC++
# make current file next to get done
ARGV[ARGIND+1] = FILENAME
# do it
nextfile
}
BEGIN {
count = 1;
}
count == 1 {
# first pass, fills an associative array
}
count == 2 {
# second pass, uses the array
}
FNR == 30 {
# handcoded length, horrible
# could also be automated calling wc -l, passing as parameter
if (count == 1) {
count = 2;
rewind(1)
}
}
在 awk 中处理两个单独的文件或同一个文件两次的惯用方法是这样的:
awk 'NR==FNR{
# fill associative array
next
}
{
# use the array
}' file1 file2
总记录数NR
只等于当前文件在第一个文件上的记录数FNR
。 next
跳过第一个文件的第二个块。然后为第二个文件处理第二个块。如果 file1
和 file2
是同一个文件,那么这将通过文件两次。