2014-01-18 3 views
0

PFB код:

for i in 3 4 5 6 7; 
do 
echo "try $i"; 
cat vm.txt | cut -f6 -d" " | awk '{ if (NR==$i) print $0 }'; 
sleep 1; 
done; 

Файл vm.txt содержит:

kthr  memory   page   disk   faults  cpu 
r b w swap free re mf pi po fr de sr s0 s1 s2 s3 in sy cs us sy id 
1 0 0 108257664 49651668 401 2616 445 0 0 0 1 3 -0 6 6 1436 13883 1427 1 47 52 
0 0 0 100580908 40823736 1533 4406 4075 1 1 0 0 0 0 0 0 3190 99090 2767 10 2 88 
1 0 0 100580720 40771708 917 5865 0 0 0 0 0 0 0 0 0 3747 137273 3557 13 2 85 
1 0 0 100580168 40721008 401 1725 0 0 0 0 0 0 0 0 0 3220 109486 2761 11 2 87 
1 0 0 100581152 40703900 199 2494 0 0 0 0 0 0 0 0 0 3727 91301 2932 9 2 89 
1 0 0 100581636 40710604 0 0 0 0 0 0 0 0 0 0 0 2472 59069 2136 8 1 91 
1 0 0 100581644 40730952 45 501 0 0 0 0 0 0 0 0 0 2939 87167 2540 9 1 90 
2 0 0 100581632 40712628 46 502 0 0 0 0 0 0 0 0 0 3251 88502 2763 9 1 90 
1 0 0 100581628 40757704 185 219 0 0 0 0 0 0 0 0 0 3058 81429 2590 9 1 90 
1 0 0 100581628 40747620 3602 52322 0 0 0 0 0 0 0 0 0 7353 127233 6077 10 5 85 

Теперь, когда я запустить эту команду:

cat vm.txt | cut -f6 -d" " | awk '{ if (NR==3) print $0 }'; 

Он работает, но он не работает в петле. Я не знаю, в чем проблема. Помощь будет высоко оценена.

+0

Обратите внимание, что символы ';'. в конце ваших команд излишне; обычно вам нужно только ';' между командами размещать * несколько * на * той же * линии. – mklement0

+0

Одно предложение, не связанное с проблемой. Цикл for с непрерывным номером ввода может быть обновлен до: 'для i в {3..7}; do echo $ i; done', поэтому вам не нужно вводить список номеров один за другим, например, если более 100 :). Во-вторых, ваш код не очень хорош, нужно много раз читать исходный файл. Вам следует называть скрипт @Ed Morton awk, который читается только один раз. – BMW

ответ

8

Аргумент к awk находится в одинарных кавычках, а переменные оболочки не интерполируются в одинарных кавычках. Вы можете изменить котировки в два раза (а затем избежать каких-либо знаков доллара, что на самом деле нужно, чтобы достучаться до awk):

for i in 3 4 5 6 7; do 
    echo "try $i" 
    cat vm.txt | cut -f6 -d" " | awk "{ if (NR==$i) print \$0 }" 
    sleep 1 
done 

или в качестве альтернативы, он может быть более устойчивым к придерживаться одинарные кавычки, но присвоить переменную оболочки к переменной Awk (это не имеет никакого значения в этом конкретном примере, но в целом, если $i может содержать пробелы, и т.д. ...):

for i in 3 4 5 6 7; do 
    echo "try $i" 
    cat vm.txt | cut -f6 -d" " | awk -v ndx="$i" '{ if (NR==ndx) print $0 }' 
    sleep 1 
done 
+0

Блестящий, это сделал трюк. Сначала я пытался избежать знака доллара, но на самом деле это не было в одиночных кавычках. Очень признателен. :) Благодаря! – user2465982

+0

Абсолютно НЕ сделайте первый подход, предложенный выше, используя двойные кавычки, поскольку он совершенно излишне усложняет ваш awk-скрипт, введя необходимость избегать знаков '' 'и, возможно, есть другие оговорки. Второй подход также имеет проблемы. Я отправлю что-нибудь, когда я получу второй, чтобы посмотреть на вопрос. –

+0

@EdMorton: У второго подхода есть только одна проблема: 'index' - это имя функции' awk' * * и поэтому не может использоваться как имя переменной; что-то вроде 'ndx' будет хорошо. По стилистической ноте форма * опции * установки переменной - например. '-v ndx =" $ i "' - * до * программы, возможно, делает цель более четкой. – mklement0

1

похоже, вы просто хотите напечатать 5-поле для линий 3 4 5 6 7. Это будет:

$ awk 'NR>=3 && NR<=7{print $5}' vm.txt 
49651668 
40823736 
40771708 
40721008 
40703900 

Если вы хотите что-то другое, обновите свой вопрос, чтобы уточнить.

+0

+1 для отличного улучшения исходного подхода (хотя это не поможет OP понять его проблему). – mklement0

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