awk: установить начало и конец матча - PullRequest
0 голосов
/ 04 мая 2018

У меня есть похожая на LaTeX таблица (столбцы разделены &):

foobar99   &     68 
foobar4    &     43 
foobar2    &     73  

Я хочу получить индекс чисел в столбце 2, используя match.

В Vim мы можем использовать \zs и \ze, чтобы установить начало и конец сопоставления. Таким образом, для точного совпадения числа в столбце 2 мы можем использовать ^.*&\s*\zs[[:digit:]]\+\ze\s*$.

Как насчет awk? Есть ли эквивалент?

EDIT:

Соответствует первой строке:

foobar99   &     68 
                 ^^   

123456789012345678 

Ожидаемый результат: 18.

EDIT2:

Я пишу сценарий awk для работы с блоком, разделенным переводом строки (следовательно, FS="\n" и RS=""). MWE выше - только один из этих блоков.

Возможный способ получить индекс числа в столбце 2 - сделать что-то подобное

split(line, cases, "&");
index = match(cases[2], /[[:digit:]]\+/);

но я ищу красивый способ сделать это.

Извиняюсь за проблему XY . Но я все еще заинтересован в сопоставлении начала / конца.

Ответы [ 3 ]

0 голосов
/ 05 мая 2018

По умолчанию awk видит три столбца в ваших данных, а столбец 2 содержит только & (а столбец 3 содержит числа). Если вы измените разделитель поля на &, то у вас будет два столбца с конечными пробелами в столбце 1 и начальными пробелами в столбце 2 (и некоторыми конечными пробелами, как это происходит; попробуйте скопировать данные из вопроса).

В awk вы можете преобразовать столбец 2 с начальными пробелами в число, добавив 0: $2 + 0 заставит его обрабатываться как число. Если вы используете $2 в числовом контексте, оно будет рассматриваться как число. И наоборот, вы можете заставить awk рассматривать поле как строку, объединяя ее с пустой строкой: $2 "" будет строкой.

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

Вы говорите, что хотите использовать match; непонятно, для чего это нужно.

awk -F'&' '{ printf "F1 [%s], F2 [%10s] = [%d] = [%-6d] = [%06d]\n", $1, $2, $2, $2, $2 }' data

Для ваших данных, которые имеют один пробел в конце первых двух строк и двойной пробел в конце третьей, вывод:

F1 [foobar99   ], F2 [       68 ] = [68] = [68    ] = [000068]
F1 [foobar4    ], F2 [       43 ] = [43] = [43    ] = [000043]
F1 [foobar2    ], F2 [      73  ] = [73] = [73    ] = [000073]

Обратите внимание, что мне не нужно явно преобразовывать $2 в число. Форматы printf обрабатывают его как строку или число в зависимости от того, использовал ли я %s или %d.

Если вам нужно, вы можете лишить конечных пробелов $1 (или даже $2), но, не зная, что еще нужно сделать, сложно с пользой продемонстрировать альтернативы.

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

0 голосов
/ 05 мая 2018

Вы можете попробовать этот способ

awk '{print index($0,$3)}' infile
0 голосов
/ 05 мая 2018

Слишком маленький контекст, поэтому простое предположение: вы пытались разбить таблицу на столбцы? С чем-то вроде awk -F '\\s*&\\s*' у вас есть второй столбец в $2.

Фактически, вы можете использовать split() для получения точного столбца строки:

split(s, a[, fs ])

Split  the  string  s into array elements a[1], a[2], ..., a[n], and 
return n.  All elements of the array shall be deleted before the split is 
performed. The separation shall be done with the ERE fs or with the field 
separator FS if fs is not given. Each array  element  shall  have  a  
string value  when  created  and,  if  appropriate, the array element 
shall be considered a numeric string (see Expressions in awk).  The 
effect of a null string as the value of fs is unspecified.

Итак, ваш второй столбец похож на

split(s, a, /\s*&\s*/)
secondColumn = a[2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...