Regex: заменить все символы после 15-го на '...' - PullRequest
2 голосов
/ 10 декабря 2008

Я пытаюсь сделать несколько простых вещей форматирования с помощью 'sed' в linux, и мне нужно использовать регулярное выражение, чтобы обрезать строку после 15-го символа и добавить '...' в конец. Примерно так:

before: this is a long string that needs to be shortened
after: this is a long ...

Может кто-нибудь показать мне, как я мог бы написать это как регулярное выражение, и, если возможно, объяснить, как это работает, чтобы я мог выучить регулярное выражение немного лучше?

Ответы [ 5 ]

17 голосов
/ 10 декабря 2008

У меня работает следующее:

echo "This is a test with more than 15 characters" | sed "s/\(.\{15\}\).\+$/\1…/"

В данном случае мы сопоставляем любой символ (.) 15 раз ({15}). Мы фиксируем текст, подобранный внутри скобок. Следующая часть (.+$) соответствует всем остальным, до конца строки. Мы заменим это на то, что записано в скобках (\1), за которым следует гиперболический эллипсис.

Чтобы удовлетворить диалект регулярного выражения sed (BRE), нам нужно экранировать некоторых персонажей.

6 голосов
/ 10 декабря 2008

Объяснение ответа Конрана Рудольфа, так как вы запросили объяснения (ах, когда я писал это, Конрад также добавил свое собственное объяснение!)

 sed "s/\(.\{15\}\).+$/\1…/"

\( 

создать группу - попросите механизм регулярных выражений запомнить, что находится внутри скобок, и назначьте первую такую ​​группу на \ 1, вторую на \ 2 и т. Д. Здесь нам потребуется только \ 1

.

Совпадение с чем угодно ...

\{15\}

... 15 раз.

\)

конец группы. Таким образом, \ 1 будет содержать первые 15 символов

 .+

сопоставить что-либо еще раз. Знак + означает «один или несколько раз», поэтому он будет соответствовать символам, превышающим 15 символов, которые мы соответствовали выше, ...

 $

... до конца строки

Теперь для сменного бита:

\1

Заменить на содержимое \ 1

...

и три точки.

Готово!

1 голос
/ 10 декабря 2008

С регулярными выражениями Perl:

$ echo 'this is a long string that needs to be shortened' \
| perl -pe 's/^(.{15}).+/$1.../'
this is a long ...

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

^

(Обратите внимание, что / - произвольный разделитель. Вместо этого могут использоваться другие символы.) ^ - это символ, представляющий начало строки в регулярном выражении. Далее регулярное выражение соответствует любому символу:

^.

A . - это символ регулярного выражения для любого символа. Но мы хотим сопоставить первые 15 символов:

^.{15}

Существует несколько различных модификаторов, которые представляют повторение. Наиболее распространенным является *, что означает 0 или более. A + обозначает 1 или более. {15} очевидно представляет ровно 15. (Обозначения {...} являются более общими. Таким образом, * можно записать {0,}, а + - это то же самое, что {1,}.) Теперь нам нужно захватить первые 15 символов чтобы мы могли использовать их позже:

^(.{15})

Все, что находится между ( и ), фиксируется и помещается в специальную переменную, называемую $1 (или иногда \1). Второй захваченный кусок будет помещен в $2 и так далее. Наконец, вам нужно сопоставить конец строки, чтобы вы могли выбросить эту часть:

^(.{15}).+

Я изначально использовал *, но, как заметил другой человек, это, вероятно, не то, что нужно, когда длина строки ровно 15 символов:

$ echo 'this is a long ' \
| perl -pe 's/^(.{15}).*/$1.../'
this is a long ...

Использование + означает, что шаблон не будет совпадать, если не будет заменен символ 16 th .

Вторая половина утверждения - это то, что печатается:

$1...

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

0 голосов
/ 10 декабря 2008

Вы действительно хотите просто убрать все после 15-го символа, или вы пытаетесь навязать максимальную длину в 15 символов? Что если строка длиной 16 символов? Все представленные решения отрубят этот лишний символ только для замены его тремя точками. (Я знаю, что Конрад и Пол использовали символ многоточия, но ОП использовал три точки в примере; мы должны получить решение по этому вопросу.)

Если вы хотите обрезать строки до максимальной длины 15 , включая три точки , вы можете сделать это:

s/^\(.\{12\}\).\{3\}.\+$/\1.../

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

0 голосов
/ 10 декабря 2008

В Perl вы можете написать s/(.{15}).*/$1.../. Я не уверен, что sed может использовать нотацию {15}, но если нет, то s/\(...............\).*/\1.../ (с 15 точками в группе).

Я никогда не могу вспомнить, нужно ли вам бежать ( при группировке в sed. Я только что попробовал, и вам нужно \( и \)

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