Как сослаться на группу регулярных выражений в регулярном выражении awk?

Вы можете вывести символ после обычного вывода, а затем удалить его:

#capture the output of "$@" (arguments run as a command)
#into the exact_output` variable
exact_output() 
{
    exact_output=$( "$@" && printf X ) && 
    exact_output=${exact_output%X}
}

Это решение соответствует стандарту POSIX.

7
21.08.2019, 15:47
5 ответов
$ echo ab aa cc de mn | perl -pe 's/(\w)\1/\1\1\1/g'
ab aaa ccc de mn

Иногда вам просто нужно признать, что есть вещи, которые awk не может сделать, но может perl.

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

13
27.01.2020, 20:13

Реализация busybox awk— единственная известная мне реализация, которая поддерживает обратные ссылки -. Он также поддерживает расширения gawkgensub()и \w:

.

Как и в случае с sub()и gsub(), вы должны использовать "..."вместо /.../и использовать \\1вместо\1(в стандарте awk, "\1"— это символ со значением 1.(^A/\1/необходимы для соответствия этому символу, в то время как "\\1"равно (хорошо было)un (der ), указанным в POSIX; также обратите внимание, что POSIX ERE не имеют обратных -ссылок, это единственная функция, которую имеют BRE, но не ERE ).

$ echo ab aa cc de mn | busybox awk '{print gensub("(\\w)\\1", "\\1\\1\\1", "g")}'
ab aaa ccc de mn

Остерегайтесь, хотя этот busybox awkне является интернационализированным , его \wсоответствует только a-zA-Z0-9_независимо от локали (то же самое для [[:alnum:]]), а многобайтовые символы -не являются поддерживается:

$ echo ee éé | busybox awk '{print gensub("(\\w)\\1", "\\1\\1\\1", "g")}'
eee éé

Со стандартными утилитами для этой работы обычно используется sed:

sed 's/\([[:alnum:]_]\)\1/&\1/g'

sedрегулярные выражения — это основные регулярные выражения, которые поддерживают обратные ссылки. Некоторые реализации sedподдерживают расширенные регулярные выражения с -rили -E, и POSIX будет указывать -Eв следующей основной версии стандарта, но по-прежнему не будет обратных ссылок (через группы захвата. на замену sбудет ). GNU и busybox sedподдерживают обратные -ссылки с -E, а FreeBSD sed— нет.

14
27.01.2020, 20:13

Не регулярное выражение, но работает. Добавит ровно 1 дополнительный символ, если все символы слова одинаковы:

echo ab aa cc de mn | \
      awk '{
        for(i=1;i<=NF;i++)
        {
          char=substr($i,1,1)
          for(j=2;j<=length($i);j++)
          {
            if(substr($i,j,1)==char) y=1
          else
            y=0
            char=substr($i,j,1)
          }
          if(y) $i=$i""char
        }
        print $0
        }'

    ab aaa ccc de mn         #output
1
27.01.2020, 20:13

К сожалению, в POSIX или любом другом awk, отличном от -busybox, требуется цикл для всех уникальных символов в каждой строке, поскольку обратные ссылки не поддерживаются в регулярном выражении:

$ cat tst.awk
{
    old = new = $0
    while (old != "") {
        char = substr(old,1,1)
        gsub(char,"",old)
        if ( char ~ /[[:alnum:]_]/ ) {
            gsub(char char,char char char,new)
        }
    }
    print new
}

$ echo ab aa cc de mn | awk -f tst.awk
ab aaa ccc de mn

Описанное выше работает, когда целевые символы не являются метасимволами регулярного выражения, как в этом случае. Если бы они могли быть метасимволами RE, вам нужно было бы экранировать их, прежде чем использовать их в контексте регулярного выражения gsub ()s. Вы можете использовать char"{2}"вместо char charв регулярном выражении gsub (), если хотите.

См. ответ @Stephane о том, как выполнить эту задачу с помощью busybox awk.

0
27.01.2020, 20:13

Это может выходить за рамки вопроса, но причина, по которой awkне поддерживает обратные ссылки, заключается в том, что awkвсегда использовались настоящие регулярные выражения, т.е. такие, которые могут быть реализованы без рекурсии конечным -конечным автоматом. Такая реализация не может поддерживать обратные ссылки в любой форме (, она может поддерживать группы захвата, хотя реализация не является прямой -прямой ).

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

«Регулярные выражения» из perl/pcre/etc, напротив, превратились в компактный синтаксис для описания рекурсивных процедур сопоставления, которые могут быть реализованы только на машине Тьюринга. Это имеет последствия для безопасности :любое окно поиска и т. д., где ненадежный пользователь может ввести такое регулярное выражение, является приглашением к атаке типа «отказ в обслуживании»; никто не может знать, сколько времени или памяти займет такой матч, и возможны только грубые меры, такие как жесткие произвольные ограничения на него и запрет упорных свиней.

Вот старая статья Расса Кокса, где все это описано более подробно.

7
27.01.2020, 20:13

Теги

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