2015-06-26 4 views
-2

У меня есть входной файл, который состоит из трех частей:Буферизация вывода с AWK

inputFirst 
inputMiddle 
inputLast 

В настоящее время у меня есть сценарий AWK, который с этим входом создает выходной файл, который состоит из двух частей:

outputFirst 
outputLast 

где outputFirst и outputLast генерируется (на лету) от inputFirst и inputLast соответственно. Однако, чтобы вычислить outputMiddle (это только одна строка), мне нужно отсканировать весь ввод, поэтому я храню его в переменной. Проблема в том, что значение этой переменной должно находиться между outputFirst и outputLast в выходном файле.

Есть ли способ решить эту проблему с помощью одного портативного AWK-скрипта, который не принимает аргументов? Есть ли переносимый способ создания временных файлов в AWK-скрипте или я должен хранить вывод с outputFirst и outputLast в двух переменных? Я подозреваю, что использование переменных будет довольно неэффективным для больших файлов.

+1

_ «Есть ли (переносной) способ решить эту проблему?» _ Ответ: _yes_. Если вы хотите получить более подробный ответ, это поможет, если вы предоставите более подробную информацию в вопросе. – John1024

+0

@ John1024 Предположим, что вход представляет собой файл из 100 чисел, а выход - это файл всех чисел, увеличивающихся на единицу, где сумма (сумма) вставлена ​​между 50: и 51-м номером, и я хочу создать этот вывод из одного сценария AWK. Есть ли способ создания временных файлов в AWK? –

+0

Это достаточно легко сделать. См. Ответ ниже. – John1024

ответ

0

Если выходной файл не слишком большой (независимо от того, что есть), сохранение outputLast в переменной вполне разумно. Первая часть, outputFirst, может (как описано) быть сгенерирована на лету. Я пробовал этот подход, и он работал нормально.

0

Все версии AWK (начиная с по меньшей мере 1985 года) могут выполнять базовое перенаправление ввода-вывода в файлы или конвейеры, как и оболочку, а также запускать внешние команды без перенаправления ввода-вывода.

Таким образом, существует множество способов приблизиться к вашей проблеме и решить ее без необходимости считывать весь входной файл в память. Наиболее оптимальное решение будет зависеть именно от того, что вы пытаетесь сделать, и от каких ограничений вы должны соблюдать.

Простой подход к более точным, например, проблемы вы описываете в своем комментарии выше, будет, возможно, пойти что-то вроде этого: сначала в виде BEGIN п два уникальных имен файлов с rand() (и определить переменные), а затем читать и просуммировать первый 50 номеров со стандартного ввода, а также записывая их во временный файл, а затем продолжая читать и суммировать следующие 50 номеров и записывать их во второй файл, а затем, наконец, в предложении END, вы должны использовать цикл для чтения первого временного файла с getline и записать его на стандартный вывод, распечатать общую сумму, затем прочитать второй временный файл таким же образом и записать его на стандартный вывод, и, наконец, вызвать system("rm " file1 " " file2) для удаления временных файлов.

+0

Добавление чисел было просто примером для иллюстрации проблемы. В моем случае обработка немного сложнее. Однако выход имеет тенденцию быть не более нескольких сотен строк, поэтому чтение его в память кажется вполне разумным в конце концов. –

+0

Итак, тогда вы на самом деле не задаете никаких вопросов, не так ли? –

0

Распечатайте «первый» вывод при обработке файла, а затем напишите остаток во временный файл до тех пор, пока вы не написали середину.

Это автономный сценарий оболочки, который обрабатывает свои входные файлы и записывает их в стандартный вывод.

#!/bin/sh 
t=$(mktemp -t middle.XXXXXXXXX) || exit 127 
trap 'rm -f "$t"' EXIT 
trap 'exit 126' HUP INT TERM 
awk -v temp="$t" "NR<500000 { print n+1 } 
    { s+=$1 } 
    NR>=500000 { print n+1 >>temp 
    END { print s }' "[email protected]" 
cat "$t" 

Для иллюстрации я использовал действительно большие номера строк. Боюсь, что ваш вопрос по-прежнему слишком расплывчатый, чтобы получить менее общий ответ, но, возможно, это поможет вам найти правильное направление.

+0

Спасибо за ввод. Однако проблема с этим подходом заключается в том, что для этого требуется сценарий оболочки для добавления временного вывода и удаления временного файла. Также неясно, как безопасно и портативно создавать и удалять временный файл в сценарии AWK. –

+0

Боюсь, что я довольно разочарован вашим комментарием. Скрипт оболочки, содержащий фрагмент Awk в качестве вспомогательной функции, является абсолютно нормальной и обычной. Если вы действительно требуете, чтобы все произошло в одном процессе, например, это довольно необычное требование, которое обязательно должно быть прописано и объяснено с обоснованием вашего вопроса; но тогда Awk - очень плохой язык реализации, и вам следует серьезно подумать о переходе на, например, Python. – tripleee

+0

Тем временем я обновил свой ответ, чтобы показать вам свободностоящий сценарий оболочки, который устанавливает ввод-вывод, а затем вызывает Awk для обработки данных. Идиома 'mktemp' /' trap' - это как безопасно настроить временный файл, который удаляется, когда скрипт завершается либо потому, что он заканчивается, либо потому, что он прерывается сигналом. – tripleee

Смежные вопросы