Используйте substr($0, 1, 4)
, чтобы получить 4 символа, которые вы хотите go в имени файла (подстрока, начинающаяся с символа 1
длины 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
Имя файла out
получено в результате конкатенации строковых литералов с результатом substr
. Эта переменная используется для определения файла, в котором вывод print
заканчивается.
>>
открывает файл в «режиме добавления», что означает, что если вы повторно откроете тот же файл, вы не теряйте предыдущее содержимое.
Тестирование:
$ 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
Использование close
- это предосторожность, предотвращающая открытие слишком большого количества файлов, но если ваш ввод не слишком большой, тогда вы можете упростить до:
awk '{ print > ("file_" substr($0, 1, 4) ".dat") }' foo.dat
Что касается производительности, вы можете попробовать отсортировать входные данные, чтобы избежать повторного открытия и закрытия одних и тех же файлов (хотя сортировка сама по себе займет время):
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 }'
Здесь я также изменил >>
на >
, поскольку awk будет открывать каждый файл только один раз.
Вы также можете избежать повторения одной и той же конкатенации строк один раз на строку, кэшируя результаты:
{
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
}
Поместите его в скрипт типа script.awk
и запустите как awk -f script.awk foo.dat
.