Преобразование awk printf String в десятичное значение

Этот общий прием работает, даже если ваш файл конфигурации curl содержит различные параметры, такие как пользовательский агент, реферер и т. Д.

Сначала предположим, что ваш файл конфигурации с именем curl_config , затем используйте awk '/ ^ [Uu] [Rr] [Ll] / {print; print "output = dummy /" ++ k; next} 1' curl_config> curl_config2 для создания нового файла конфигурации curl, который постепенно добавляет другой вывод имена файлов под каждым url / URL:

Пример:

[xiaobai@xiaobai curl]$ cat curl_config
URL = "www.google.com"
user-agent = "holeagent/5.0"

url = "m12345.google.com"
user-agent = "holeagent/5.0"

URL = "googlevideo.com"
user-agent = "holeagent/5.0"
[xiaobai@xiaobai curl]$ awk '/^[Uu][Rr][Ll]/{print;print "output = dummy/"++k;next}1' curl_config  > curl_config2 
[xiaobai@xiaobai curl]$ cat curl_config2
URL = "www.google.com"
output = dummy/1
user-agent = "holeagent/5.0"

url = "m12345.google.com"
output = dummy/2
user-agent = "holeagent/5.0"

URL = "googlevideo.com"
output = dummy/3
user-agent = "holeagent/5.0"
[xiaobai@xiaobai curl]$ 

Затем mkdir dummy , чтобы создать каталог для хранения этих временных файлов. Создайте сеанс inotifywait (замените sed '/ google / q' на свой sed '/ mortgage / q'):

[xiaobai@xiaobai curl]$ rm -r dummy; mkdir dummy;
[xiaobai@xiaobai curl]$ rm final 
[xiaobai@xiaobai curl]$ inotifywait -m dummy -e close_write | while read path action file; do echo "[$file]">> final ; sed '/google/q' "$path$file" >> final; echo "$path$file"; rm "$path$file"; done;
Setting up watches.
Watches established.

Откройте другой сеанс bash / терминала, файл rm final , если exist, затем запустите ваш curl с файлом curl_config2, созданным на первом шаге выше:

[xiaobai@xiaobai curl]$ curl -vLK curl_config2
...processing

Теперь взгляните на сеанс inotifywait, он распечатает последний записанный файл закрытия, sed и сразу же удалит его после завершения:

[xiaobai@xiaobai curl]$ inotifywait -m dummy -e close_write | while read path action file; do echo "[$file]">> final ; sed '/google/q' "$path$file" >> final; echo "$path$file"; rm "$path$file"; done;
Setting up watches.
Watches established.
dummy/1
dummy/3

Наконец, вы вы можете увидеть ваш вывод с именем final , разделитель [1 и 3] генерируется из echo "[$ file]" >> final выше:

enter image description here

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

3
29.07.2018, 15:47
4 ответа

Задача:

sdout the load avg from top in a decimal form like(e.g 0.23)

Решение:

top -b -n  1  | perl -lane 'print "$1.$2" if /load average: (\d+)[,.](\d+)/'

Примечания:

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

Как указал @terdon , uptimeможет быть лучшей отправной точкой, чем topв этом случае.

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

В Perl числа автоматически -преобразуются в строки и наоборот -наоборот. Любая числовая операция может быть выполнена над строкой, представляющей число. например.print "$1.$2"+11.11


Вопрос 2:

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

How Can I convert the string value to decimal/float/integer ?

Лучше записывать как :Выполнение числовых сравнений строк с помощью Chef InSpec .

Решение:

Преобразование строки в числовой формат с помощью to_iили to_f.

Пример:

describe command("echo 1.00") do
    its("stdout.to_f") { should be < 1.03 }
end

Пояснение:

Логично, что стандартный вывод рассматривается как строка.Также весьма разумно числовое сравнение требует, чтобы два числа были... числами. К счастью, преобразование можно выполнить с помощью удобных строковых методов Ruby :to_i, to_f, to_rи to_c.

1
27.01.2020, 21:13

Из gawk :Суммирование чисел с плавающей запятой, отформатированных с разделителем-запятой:

Ответ заключается в использовании опции --use-lc-numericgawk.

--use-lc-numeric

This forces gawk to use the locale's decimal point character when parsing input data. Although the POSIX standard requires this behavior, and gawk does so when --posix is in effect, the default is to follow traditional behavior and use a period as the decimal point, even in locales where the period is not the decimal point character. This option overrides the default behavior, without the full draconian strictness of the --posix option.

В вашем случае эта команда должна работать:

top -b -n 1 | awk --use-lc-numeric '/load average/ { printf "%f\n", $10}'

2
27.01.2020, 21:13

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

  1. Используйте локаль C дляtop:

    LC_ALL=C top -b -n  1  | awk  '/load average/ { printf "%f\n",$10}'
    

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

  2. Замените запятую точкой:

    top -b -n  1  | awk  '/load average/ { sub(/,/,".",$10); printf "%f\n",$10}'
    
  3. В GNU awkиспользуйте флаг --use-lc-numeric, предложенный @Leo , или используйте POSIXLY_CORRECT=1 awk.

  4. Или используйте совместимую с POSIX awkреализацию, такую ​​как One True awk , которая по умолчанию должна анализировать и печатать числа в соответствии с правилами локали.

Обратите внимание, что более переносимой командой для получения среднего значения нагрузки является uptime.

2
27.01.2020, 21:13

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

Это воспроизводит вашу проблему:

$ LC_ALL=de_DE top -bn 1 | awk 'NR==1'
top - 08:37:07 up 1 day, 10:22,  5 users,  load average: 0,17, 0,24, 0,26

Как видите, в числах используется запятая в качестве десятичного разделителя. Вам нужно что-то похожее на:

$ LC_ALL=en_US top -bn 1 | awk 'NR==1'
top - 08:38:28 up 1 day, 10:23,  5 users,  load average: 0.56, 0.34, 0.30

Но это будет зависеть от того, какие локали были установлены (проверьте с помощьюlocale -a)в вашей системе. Всегда доступна локаль C.

$ LC_ALL=C top -bn 1 | awk 'NR==1'
top - 08:40:35 up 1 day, 10:25,  5 users,  load average: 0.50, 0.39, 0.31

Но использовать top только для извлечения первой строки — это излишество.Лучше использовать время безотказной работы:

$ LC_ALL=C uptime
08:42:08 up 1 day, 10:27,  5 users,  load average: 0.35, 0.37, 0.31

А еще лучше прочтите файл /proc/loadavg

$ cat /proc/loadavg 
0.29 0.34 0.30 1/468 15084

На что, кстати, не влияет локаль. Первое число — это средняя нагрузка за 1 минуту, просто выберите его и распечатайте в любом формате:

$ awk '{printf( "%s\n %f\n %d\n", $1, $1, $1 )}' /proc/loadavg
0.35
0.350000
0

Для использования средней нагрузки 1, 5 и 15 минут:

$ awk '{printf( "%7.3f %7.3f %5.2f\n", $1, $2, $3 )}' /proc/loadavg
 0.150   0.340  0.33
1
27.01.2020, 21:13

Теги

Похожие вопросы