Вы можете вывести символ после обычного вывода, а затем удалить его:
#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.
$ 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.
Реализация busybox awk
— единственная известная мне реализация, которая поддерживает обратные ссылки -. Он также поддерживает расширения gawk
gensub()
и \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
— нет.
Не регулярное выражение, но работает. Добавит ровно 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
К сожалению, в 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.
Это может выходить за рамки вопроса, но причина, по которой awk
не поддерживает обратные ссылки, заключается в том, что awk
всегда использовались настоящие регулярные выражения, т.е. такие, которые могут быть реализованы без рекурсии конечным -конечным автоматом. Такая реализация не может поддерживать обратные ссылки в любой форме (, она может поддерживать группы захвата, хотя реализация не является прямой -прямой ).
Идея с awk
, насколько я понимаю, заключается в том, что вы должны использовать регулярное выражение для прямого времени -и памяти -ограниченных совпадений, и его C -как тьюринг -полный язык для чего-то более сложного, чем это.
«Регулярные выражения» из perl/pcre/etc, напротив, превратились в компактный синтаксис для описания рекурсивных процедур сопоставления, которые могут быть реализованы только на машине Тьюринга. Это имеет последствия для безопасности :любое окно поиска и т. д., где ненадежный пользователь может ввести такое регулярное выражение, является приглашением к атаке типа «отказ в обслуживании»; никто не может знать, сколько времени или памяти займет такой матч, и возможны только грубые меры, такие как жесткие произвольные ограничения на него и запрет упорных свиней.
Вот старая статья Расса Кокса, где все это описано более подробно.