2015-02-08 2 views
0

У меня есть файл, который реплицирует результаты из команды show processlist из mySQL. файл выглядит следующим образом:Использование AWK и определение результатов для переменных bash/массивов?

*************************** 1. row *************************** 
Id: 1 
User: system user 
Host: 
db: NULL 
Command: Connect 
Time: 1030455 
State: Waiting for master to send event 
Info: NULL 
*************************** 2. row *************************** 
Id: 2 
User: system user 
Host: 
db: NULL 
Command: Connect 
Time: 1004 
State: Has read all relay log; waiting for the slave 
     I/O thread to update it 
Info: NULL 

И продолжает идти на еще несколько раз в одной и той же структуре.

Я хочу использовать AWK только для получения этих параметров: времени, идентификатора, команды и состояния и хранения каждого из этих параметров в другую переменную или массив, чтобы впоследствии использовать/печатать их в своей оболочке bash.

Проблема в том, что я довольно плохой с AWK, я не знаю, как обособлять параметры, которые я хочу от файла, а также устанавливать их как переменную bash или массив.

Большое спасибо за помощь!

EDIT: Вот мой код до сих пор

echo "Enter age" 
read age 
cat data | awk 'BEGIN{ RS="row" 
FS="\n" 
OFS="\n"} 
{ print $2,$7} 
' | awk 'BEGIN{ RS="Id"} 
{if ($4 > $age){print $2}}' 

Файл «данные» содержит блоки, как я вставил выше. Код должен, если введенный «возраст» меньше, чем параметр «Время» в файле данных (который составляет 4 доллара в моем awk-коде), верните параметр ID, но он ничего не возвращает.

Если удалить, если заявление и напечатать $ 4 вместо $ 2 это мой выход

Enter age 
1 

1030455 
1004 
2144 
2086 
0 

Так что я думал, может быть, что пустая строка как-то испортить мой AWK печать? Есть ли простой способ игнорировать эту пустую строку, сохраняя мои другие данные?

+0

Вставьте выход в вопрос, пометьте его мышью, а затем используйте инструмент '{}' на панели инструментов, чтобы пометить его как литеральный код. – Barmar

+0

'awk' не может напрямую устанавливать переменные оболочки. То, что вы можете сделать, это передать вывод 'awk' в оболочку' при чтении var1 var2 var3' loop. – Barmar

+0

Эй, спасибо, thats nifty :) – gotner

ответ

2

Это, как вы будете использовать AWK для получения значения, которые в виде набора вкладок полей, разделенных на каждой строке в блоке «строки» от входа:

$ cat tst.awk 
BEGIN { 
    RS="[*]+ [[:digit:]]+[]. row [*]+\n" 
    FS="\n" 
    OFS="\t" 
} 
NR>1 { 
    sub(/\n$/,"")  # remove the trailing newline 
    gsub(/\n\s+/," ") # compress all multi-line fields into single lines 
    gsub(OFS," ")  # ensure the only OFS in the output IS between fields 

    delete n2v 
    for (i=1; i<=NF; i++) { 
     name = gensub(/:.*/,"","",$i) 
     value = gensub(/^[^:]+:\s+/,"","",$i) 
     n2v[name] = value 
    } 

    if (n2v["Time"]+0 > age) { # force a numeric comparison 
     print n2v["Time"], n2v["Id"], n2v["Command"], n2v["State"] 
    } 
} 

$ awk -v age=2000 -f tst.awk file 
1030455 1  Connect Waiting for master to send event 

Если целевой возраст уже хранится в переменной оболочки просто инициализировать переменную AWK из переменной оболочки одного и того же имени:

$ age="2000" 
$ awk -v age="$age" -f tst.awk file 

выше использует GNU AWK для мульти-полукокса RS (который вы уже имели), gensub(), \s и delete array.

Когда вы говорите «и сохранить каждую из этих параметров в другую переменную или массив», это может означать одно из нескольких вещей, так что я оставлю эту часть до вас, но вы могли бы искать что-то вроде:

arr=($(awk '...')) 

или

awk '...' | 
while IFS="\t" read -r Time Id Command State 
do 
    <do something with those 4 vars> 
done 

, но на сегодняшний день, скорее всего, ситуация такова, что вы не хотите использовать оболочку на всех, но вместо того, чтобы просто остаться в AWK.

Помните - каждый раз, когда вы пишете цикл в оболочке, просто для управления текстом у вас неправильный подход. Оболочка UNIX - это среда, из которой можно вызвать инструменты UNIX, а инструмент UNIX для общей обработки текста - awk.

Пока вы не отредактируете свой вопрос, чтобы рассказать нам больше о вашей проблеме, мы не можем догадаться, какое правильное решение из этого момента.

1

На первом уровне у вас есть оболочка, которую вы используете для запуска любого другого дочернего процесса. Невозможно изменить родительскую среду из дочернего процесса. Когда вы запускаете файл сценария bash (который имеет +x справа), он генерируется как новый процесс (дочерний элемент). Он может установить его собственную среду, но когда он закончится, вы вернетесь к оригиналу (родительскому).

Вы можете установить некоторые переменные на bash и export им в свою среду. Это будет унаследовано его детьми. Однако это невозможно сделать в противоположном направлении (родитель не может наследовать от своего ребенка).

Если вы хотите выполнить некоторые команды из файла сценария в текущем контексте bash, вы можете source файл сценария. source ./your_script.sh или . ./your_script.sh сделают это за вас.

Если вам нужно запустить awk фильтровать некоторые данные для вас и сохранить результаты в Баш вы можете сделать:

awk ... | read foo 

Это работает как read является оболочка функции Buildin, а не внешний процесс (проверка type read, help , help read, man bash, чтобы проверить его самостоятельно).

или:

foo=`awk ....` 

Есть много других конструкций, которые можно использовать. Какой бы ни был сценарий bash, пожалуйста, сравните свой код с bash pitfalls webpage.

+0

Один простой (но не очень эффективный) способ обработки пустых строк - 'strings'. – pawel7318

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