Use substr($0, 1, 4) to get the 4 characters that you want to go in the filename (a substring starting at character 1 of length 4):
awk '{
out = "file_" substr($0, 1, 4) ".dat" # set filename
if (out != prev) close(prev) # close previous file
print >> out # write to file
prev = out # remember filename to check on next line
}' foo.dat
The filename out comes from the result of concatenating the string literals with the result of substr. This variable is used to determine the file that print's output ends up in.
>> opens a file in "append mode", which means that if you re-open the same file, you don't lose the previous content.
Testing it out:
$ awk '{ out = "file_" substr($0, 1, 4) ".dat"; if (out != prev) close(prev); print >> out; prev = out }' foo.dat
$ cat file_1985.dat
1985tiny dancer
1985hey jude
$ cat file_1986.dat
1986largechicken
The use of close is a precaution to prevent opening too many files, but if your input isn't too big then you can simplify to just:
awk '{ print > ("file_" substr($0, 1, 4) ".dat") }' foo.dat
Regarding performance, you could try sorting the input, to avoid opening and closing the same files repeatedly (although sorting would itself take time):
sort -s -k1.1,1.4 foo.dat | awk '{ out = "file_" substr($0, 1, 4) ".dat"; if (out != prev) close(prev); print > out; prev = out }'
Here I also changed the >> to > since awk will only open each file once.
You could also avoid repeating the same string concatenation once per line by caching the results:
{
ss = substr($0, 1, 4)
if (!(ss in outs)) {
outs[ss] = "file_" ss ".dat"
}
out = outs[ss]
if (out != prev) close(prev)
print >> out
prev = out
}
Put it in a script like script.awk and run it like awk -f script.awk foo.dat.