AWK: Gehe die Datei zweimal durch und erfülle dabei verschiedene Aufgaben.

Ich verarbeite eine ziemlich große Sammlung von Tweets und möchte für jeden Tweet die Erwähnungen (Namen anderer Benutzer, denen ein @ vorangestellt ist) erhalte@), wenn der genannte Benutzer auch in der Datei ist:

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"

Ich habe die Datei bereits mit GAWK verarbeitet. Anstatt sie in Python oder C erneut zu verarbeiten, habe ich mich entschlossen, dies meinem AWK-Skript hinzuzufügen. Ich kann jedoch keine Möglichkeit finden, die gleiche Datei zu bearbeiten, indem für jede Datei ein anderer Code ausgeführt wird. Die meisten Lösungen setzen voraus, dass AWK mehrmals aufgerufen wird, aber dann würde ich das assoziative Array verlieren, das ich im ersten Durchgang erstellt habe.

Ich könnte es auf sehr hackige Weise tun (wiecat 'die Datei zweimal durchlaufen,sed, um allen Zeilen in jedem @ ein anderes Präfix hinzuzufügcat), aber ich möchte diesen Code in ein paar Monaten verstehen können, ohne mich selbst zu hassen.

Was wäre der AWK-Weg, um dies zu tun?

PD:

Der weniger schreckliche Weg, den ich gefunden habe:

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)
    }
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage