Можно ли определить тип переменной awk?

Ubuntu 13.10 (saucy в вашем списке) является EOL. Вам следует обновить [источник]

Поддержка Ubuntu 13.10 закончилась 17 июля 2014 г.

Вы можете обновиться из терминала, как описано в ultimate guide for uprading to new version

do-release-upgrade 

или следуя любому другому руководству, которое вы можете найти в интернете, например howtoforge:

откройте /etc/apt/sources.list:

sudo gedit /etc/apt/sources.list

Вот как выглядит файл для Linux Mint 13:

Теперь замените maya на nadia и все вхождения saucy на quantal

Затем обновите && upgrade

sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get upgrade
sudo reboot 

3
05.05.2016, 17:38
2 ответа

Для уточнения, только строки, поступающие из нескольких источников (здесь цитируется спецификация POSIX):

  1. Переменные поля
  2. Ввод из функции getline()
  3. FILENAME
  4. Элементы массива ARGV
  5. Элементы массива ENVIRON
  6. Элементы массива, созданные функцией split()
  7. Назначение переменной командной строки
  8. Назначение переменной из другого числового строковая переменная

должна считаться числовой строкой , если ее значение оказывается числовым (допуская начальные и конечные пробелы, с вариациями между реализациями для поддержки шестнадцатеричного, восьмеричного, inf, nan...) .

Литеральная строковая константа "3.14" является строкой, а не строкой, поскольку она не получена ни из одного из этих источников.

x = "3.14"; if (x == 3.14) print "yes"

печатает да, но это потому, что он выполняет лексическое сравнение (в зависимости от реализации, используя memcmp(), strcmp() или strcollate() ) из 3.14 и преобразование в строку (через строку формата CONVFMT, %.6g в gawk и многих других реализациях) этого номера 3.14. То есть с этим значением CONVFMT, (x == 3,14) совпадает с (x == "3,14").

(x < 12) будет ложным, потому что 3.14 сортируется лексически после 12 (то же, что ("3.14" < "12")). С CONVFMT = "%.6e", (x == 3.14) также вернет false, потому что это становится ("3.14" == "3.140000e+00") .

С другой стороны, в:

"echo \"3.1400 \"" | getline x
if (x == 3.14) print "yes"
if (x < 12) print "yes"

yes печатается дважды независимо от значения CONVFMT, потому что выполняется численное сравнение. x — это strnum, потому что он получен из getline и имеет числовое значение.

Тем не менее, он по-прежнему сохраняет свое строковое значение. print x напечатает "3.1400" независимо от значения OFMT или CONVFMT.

И:

"echo 3.14 foo" | getline x
if (x == 3.14) print "yes"

Не печатает да. x происходит от getline, но не имеет числового значения (из-за foo). Это обычная строка, как если бы вы написали x = "3.14 foo". Тем не менее, вы сможете выполнять с ним числовые операции:

print x + 1

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

Итак, (x+0 == 3.14) и (x+0 < 12) также вернут true. x+0 является числовым, поэтому у нас есть числовое сравнение.

Обратите внимание, что inf, nan, Infinity не распознаются как числа с плавающей запятой inf или nan. специальные значения в качестве констант, но в некоторых реализациях awk вы можете вместо этого использовать ("inf"+0).

3
27.01.2020, 21:08

Awk имеет 4 типа: "число", "строка", "числовая строка" и "неопределенное".Здесь является функцией для обнаружения того, что:

function o_class(obj,   q, x, z) {
  q = CONVFMT
  CONVFMT = "% g"
    split(" " obj "\1" obj, x, "\1")
    x[1] = obj == x[1]
    x[2] = obj == x[2]
    x[3] = obj == 0
    x[4] = obj "" == +obj
  CONVFMT = q
  z["0001"] = z["1101"] = z["1111"] = "number"
  z["0100"] = z["0101"] = z["0111"] = "string"
  z["1100"] = z["1110"] = "strnum"
  z["0110"] = "undefined"
  return z[x[1] x[2] x[3] x[4]]
}

Для третьего аргумента split вам нужно что-то, что не является пробелом, и не является частью obj, иначе он будет рассматриваться как разделитель. Я выбрал \1 основано на предложении Стефана. Функция выполняет внутреннюю CONVFMT переключение, поэтому он должен возвращать правильный результат независимо от значения CONVFMT во время вызова функции:

split("12345.6", q); print 1, o_class(q[1])
CONVFMT = "%.5g"; split("12345.6", q); print 2, o_class(q[1])
split("nan", q); print 3, o_class(q[1])
CONVFMT = "%.6G"; split("nan", q); print 4, o_class(q[1])

Результат:

1 strnum
2 strnum
3 strnum
4 strnum

Полный набор тестов:

print 1, o_class(0)
print 2, o_class(1)
print 3, o_class(123456.7)
print 4, o_class(1234567.8)
print 5, o_class(+"inf")
print 6, o_class(+"nan")
print 7, o_class("")
print 8, o_class("0")
print 9, o_class("1")
print 10, o_class("inf")
print 11, o_class("nan")
split("00", q); print 12, o_class(q[1])
split("01", q); print 13, o_class(q[1])
split("nan", q); print 14, o_class(q[1])
split("12345.6", q); print 15, o_class(q[1])
print 16, o_class()

Результат:

1 number
2 number
3 number
4 number
5 number
6 number
7 string
8 string
9 string
10 string
11 string
12 strnum
13 strnum
14 strnum
15 strnum
16 undefined

Заметная слабость: если вы предоставляете «числовую строку» любого из далее функция будет неправильно возвращать «число»:

  • integer
  • inf
  • -inf

Для целых чисел это объясняется:

Числовое значение, точно равное значению целого числа должен быть преобразуется в строку эквивалентом вызова функции sprintf со строкой %d в качестве аргумента fmt

Однако inf и -inf ведут себя так же; то есть ни один из на приведенное выше может повлиять переменная CONVFMT:

CONVFMT = "% g"
print "" .1
print "" (+"nan")
print "" 1
print "" (+"inf")
print "" (+"-inf")

Результат:

 0.1
 nan
1
inf
-inf

На практике это не имеет особого значения, см. Duck test.

6
27.01.2020, 21:08

Теги

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