Запретить awk преобразовывать строку, начинающуюся с 0, в oct

Это стоило мне сна.

Предположим, у вас есть файл a_file.txt, как показано ниже.

1000    JUC_0000    1
2494    JUC_AAAA    2
2495    JUC_BBBB1   3
2495    JUC_BBBB2   4
4676    JUC_CCCC    5
4677    JUC_DDDD1   6
4677    JUC_DDDD2   7

Если ты бежишь

awk '{if($1==4677){print $0;}}' a_file.txt

Вы получите то, что ожидаете:

4677    JUC_DDDD1   6
4677    JUC_DDDD2   7

Однако если вы запустите

awk '{if($1==04677){print $0;}}' a_file.txt

Вы могли быть (я) удивлены, узнав

2495    JUC_BBBB1   3
2495    JUC_BBBB2   4

Похоже, что awk интерпретирует 04677 как восьмеричное представление 2495 и работает с ним.

Два вопроса:

  1. Верна ли моя интерпретация результата?
  2. Есть ли способ запретить awk интерпретировать числа, начинающиеся с 0, как восьмеричные числа и вместо этого использовать их десятичную интерпретацию?
  3. У gawk такое же поведение, и можно ли его изменить?

person W7GVR    schedule 07.03.2017    source источник
comment
Is my interpretation of the result correct? да, ваша интерпретация верна   -  person Jose Ricardo Bustos M.    schedule 07.03.2017
comment
(2) Только я могу думать о $1==int("04677") ......   -  person Jose Ricardo Bustos M.    schedule 07.03.2017
comment
Does gawk have the same behaviour да ... is it possible to change it? без понятия   -  person Jose Ricardo Bustos M.    schedule 07.03.2017
comment
Хосе: Спасибо. Преобразование int должно работать.   -  person W7GVR    schedule 07.03.2017
comment
Джеймс: Это не работает, поскольку столбец в a_file.txt не содержит начального 0.   -  person W7GVR    schedule 07.03.2017
comment
Учитывая ваши комментарии ниже, вы на самом деле не выполняете код, который вы указали в своем вопросе, и поэтому это не имеет ничего общего с восьмеричными и десятичными числами. См. stackoverflow.com/a/42653696/1745001.   -  person Ed Morton    schedule 07.03.2017


Ответы (3)


  1. Числа, начинающиеся с нуля в начале, - это octal числа в awk. 2495 - десятичное значение восьмеричного числа 4677.

  2. Десятичного числа, начинающегося с 0, нет, за исключением самого 0.

  3. Да и не изменится.


Кстати, идеоматическая версия

awk '{if($1==4677){print $0;}}' file

is

awk '$1==4677' file
person hek2mgl    schedule 07.03.2017

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

$ awk '$1=="04677"' file

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

$ awk '$1==04677+0' file
person karakfa    schedule 07.03.2017
comment
Спасибо. Проблема возникла из-за запуска awk в сценарии, где ключ 04677 был строкой, но файл имел числовой первый столбец (без начальных нулей). Параметр 04677 не работает, потому что строка в файле не содержит начального 0. Я думал, что это не имеет значения, если я оставлю его числовым, но восьмеричное преобразование застало меня врасплох. Я считаю, что в этом случае хорошо подойдет вариант 04677 + 0. - person W7GVR; 07.03.2017
comment
@gvrocha этот комментарий означает, что ваш вопрос не представляет вашу настоящую проблему, и поэтому мы все пытаемся помочь вам решить проблему, которой у вас нет. См. stackoverflow.com/a/42653696/1745001. - person Ed Morton; 07.03.2017

Когда вы пишете $1==04677 вместо $1==4677, вы указываете awk обрабатывать 04677 как восьмеричное число, точно так же, как если бы вы написали $1==0x4677, вы бы сказали awk рассматривать его как шестнадцатеричное, а с $1==4677"" вы бы указание awk рассматривать его как строку. Если вы этого не хотите, просто не делайте этого.

ОБНОВЛЕНИЕ: относительно комментария, сделанного вами в ответе @ karakfa:

Проблема возникла из-за запуска awk в сценарии, где ключ 04677 был строкой, но файл имел числовой первый столбец (без начальных нулей). Параметр «04677» не работает, потому что строка в файле не содержит начального 0. Я думал, что это не имеет значения, если я оставлю его числовым, но восьмеричное преобразование застало меня врасплох. Я считаю, что в этом случае хорошо подойдет вариант 04677 + 0.

То, что вы только что описали в этом комментарии, - это совершенно другая проблема, чем вы указали в своем вопросе. Теперь вы больше не сравниваете десятичное число с восьмеричным, вы сравниваете число со строкой, и в этом случае используется операция сравнения строк (см. https://www.gnu.org/software/gawk/manual/gawk.html#Typing-and-Comparison), поэтому 4677! = "04677", потому что первый символ 4677 - это "4", а первый символ 04677 - "0". Это не имеет ничего общего с восьмеричным представлением числа. Да, использование "04677"+0 будет работать, потому что это преобразует строку в число (4677), и в результате вы получите числовое, а не строковое сравнение.

person Ed Morton    schedule 07.03.2017