AWK - странное различие между printf и sprintf при использовании substr - PullRequest
0 голосов
/ 13 февраля 2019

Прошло много времени с тех пор, как я использовал AWK, но теперь у меня есть XML-файл, в котором я хотел бы увеличить Id для определенного столбца;так что это отличная задача для AWK.Теоретически, чтобы увеличить Id, строка анализируется, вы выводите Id в переменную ++ it и реконструируете строку для печати в результирующий поток.Однако, когда я использую переменную (x = sprintf (...)), я получаю странные результаты, поэтому я использовал printf для отладки.А теперь странная часть: printf выдает точно правильный Id, но переменная получает мусор, хотя они имеют одинаковый ввод и синтаксис ... Должно быть, это немного глупо, конечно, но я не могу это понять.

Все идентификаторы имеют вид:

<column name="Id" type="System.Int32">x</column>

Это код:

#!/bin/ksh
cd /mnt/c/J/D/Work/GIT/Repos/SkillsNG/SkillsNG.WebTests/Snapshots
print -n "Snapshot name: "
read snapshot
defaultId=0
print -n "Start increasing from Id [$defaultId]":
read id

[[ "$id" = '' ]] && id=$defaultId

cat $snapshot | awk -F '>' 'BEGIN {process=0;} {
if (match($0, /SecurityPermissions/))
     {process=1;}
else
  {
    if (!process)
    {
       # just dump all tables up to SecurityPermissions, no processing needed
       print;
       next;
    }
  }
if (match($1, /<column name="Id" type="System.Int32"/))
  {
   if(match($2,/[0-9]*/))
   {
      printf "param 1: %s\n", $1
      printf "param 2: %s\n", $2
      printf "Id value : %s\n", substr($2, 1, index($2,"\<")-1);

      val = sprintf("%s", substr($2,1, index($2,"\<")-1));
      printf "value in variable: %s\n", $val;
      newval = strtonum(val);
      printf "new: %s\n",  $newval

   }
 }
 else print $0;
}' > $snapshot.new
# mv $snapshot $snapshot.old
# mv $snapshot.new $snapshot
cd -

А это простой тест XML:

    <snapshot culture="en-US">
  <table name="[dbo].[SecurityPermissions]">
    <row>
      <column name="Id" type="System.Int32">1</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">1</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">2</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">50</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">3</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">51</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">4</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">52</column>
      <column name="Access" type="System.Int32">3</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">5</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">53</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">6</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">54</column>
      <column name="Access" type="System.Int32">3</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">7</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">56</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">8</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">57</column>
      <column name="Access" type="System.Int32">3</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">9</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">77</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">10</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">78</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
    <row>
      <column name="Id" type="System.Int32">11</column>
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">80</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
  </table>
</snapshot>

Файл результатов:

<snapshot culture="en-US">
  <table name="[dbo].[SecurityPermissions]">
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 1</column
Id value : 1
value in variable:       <column name="Id" type="System.Int32"
new:       <column name="Id" type="System.Int32"
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">1</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 2</column
Id value : 2
value in variable: 2</column
new: 2</column
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">50</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 3</column
Id value : 3
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">51</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 4</column
Id value : 4
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">52</column>
      <column name="Access" type="System.Int32">3</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 5</column
Id value : 5
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">53</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 6</column
Id value : 6
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">54</column>
      <column name="Access" type="System.Int32">3</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 7</column
Id value : 7
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">56</column>
      <column name="Access" type="System.Int32">1</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 8</column
Id value : 8
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">57</column>
      <column name="Access" type="System.Int32">3</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 9</column
Id value : 9
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">77</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 10</column
Id value : 10
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">78</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
    <row>
param 1:       <column name="Id" type="System.Int32"
param 2: 11</column
Id value : 11
value in variable: 
new: 
      <column name="GroupId" type="System.Int32">1</column>
      <column name="Securable" type="System.Int32">80</column>
      <column name="Access" type="System.Int32">15</column>
    </row>
  </table>
</snapshot>

Как видно из файла результатов, значение Id (через printf) работает правильно, но та же конструкция переменной (через sprintf) создает мусор.Кто-нибудь понял, что происходит?Заранее спасибо.Приветствия, DJ

1 Ответ

0 голосов
/ 13 февраля 2019

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

Если вы хотите увеличить это конкретное значение, вы можете использовать следующую команду xmlstarlet:

 $ xmlstarlet ed --update '//table/row/column[@name="Id"]' -x ".+1" test.xml

Читается так: xmlstarlet будет (ed) редактировать файл test.xml путем (--update) обновления всех узлов, соответствующих выражению XPath ('//table/row/column[@name="Id"]' :: все узлы column дочерний элемент row дочерний элемент table с атрибутом name, равным Id), и измените его значение с помощью выражения XPath -x ".+1"(увеличить текущее значение (.))

Чтобы ответить на ваш вопрос: вы получите неожиданные результаты с помощью awk, так как вы ссылаетесь на некоторые переменные, используя $.Пример:

val = sprintf("%s", substr($2,1, index($2,"\<")-1));
printf "value in variable: %s\n", $val;

В первой строке вы вычисляете значение val, но во второй строке вы используете $val.Последний фактически возвращает значение поля с номером val.Так что если val=2, то $val вернет $2, то есть содержимое второго поля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...