Невозможно заставить указанное регулярное выражение работать в команде sed - PullRequest
6 голосов
/ 21 июня 2020

Я пытаюсь заставить следующие регулярные выражения работать в команде sed в bash.

^[^<]?(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*))[^>]?$

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

Вы можете найти демонстрацию вышеуказанного регулярного выражения в здесь.

Мое требование: Я хочу заключить каждый URL внутрь <>. Если URL-адрес уже заключен; затем добавьте его к результату, как показано в приведенной выше ссылке на регулярное выражение.

Пример ввода: (в файле с именем website.txt)

// List of all legal urls
https://www.google.com/
https://www.fakesite.co.in
https://www.fakesite.co.uk
<https://www.fakesite.co.uk>
<https://www.google.com/>

Ожидаемый результат: (в файле с именем output.txt)

<https://www.google.com/> // Please notice every url is enclosed in the <>.
<https://www.fakesite.co.in>
<https://www.fakesite.co.uk>
<https://www.fakesite.co.uk> // Please notice if the url is already enclosed in <> then it is appended as it is.
<https://www.google.com/>

То, что я пробовал в sed:

  1. Поскольку Я плохо разбираюсь в командах bash; поэтому раньше я не мог правильно захватить группу в sed, но после прочтения этого ответа; Я понял, что нам нужно избежать скобок, чтобы иметь возможность захватить его.

  2. Somewhere; Я читал, что осмотр не поддерживается в sed (на основе GNU), поэтому я тоже удалил поиск; но это тоже не сработало. Если он не поддерживает осмотр, я использовал это регулярное выражение, и оно послужило моей цели.

  3. Затем; это моя последняя попытка с командой sed:

    sed 's@^[^<]?(https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&/=]*))[^>]?$@<\1>@gm;t;d' websites.txt > output.txt
    

Моя точная проблема:

Как я могу сделать указанную выше команду работать должным образом. Если вы запустите пример команды, который я приложил выше, в пункте 3; вы бы увидели, что он неправильно заменяет содержимое. Он просто выгружает содержимое websites.txt в output.txt. Но в демонстрации регулярных выражений; прикрепленный выше, он работает правильно, т.е. все незакрытые веб-сайты заключены в <>. Любые предложения будут полезны. Я предпочтительно хочу, чтобы это было в sed, но если возможно, я могу преобразовать указанную выше команду и в awk ? Если вы можете, пожалуйста, помогите мне и с этим; Я буду очень признателен. Спасибо

Ответы [ 3 ]

4 голосов
/ 21 июня 2020

После долгой работы я заставил свою команду sed работать. Ниже приведена команда, которая сработала.

sed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t' websites.txt > output.txt

Здесь вы можете найти пример реализации команды в .

Так как регулярное выражение уже выполнил требование человека, для которого я пишу это требование; Мне нужна была помощь только по синтаксису команд (хотя любые улучшения приветствуются); Я хочу, чтобы команда работала с тем же шаблоном регулярного выражения.

Вещи, о которых я не знал ранее и узнал сейчас: Я ничего не знал о флаге -E. Теперь я знаю; что -E использует «расширенный» синтаксис POSIX («ERE»). Спасибо @ GordonDavisson и @ Sundeep . Дальнейшее чтение.

Я не знал с ясностью, что sed не поддерживает просмотр. Но теперь я знаю, что sed не поддерживает осмотр. Спасибо @ dmitri-chubarov . Дополнительная литература

Я не знал, что sed также не поддерживает группы без захвата. Спасибо @ Sundeep за решение этой части. Дополнительная литература

Я не знал о GNU sed как об особом c инструменте командной строки. Спасибо @ oguzismail за это. Дополнительная литература.

2 голосов
/ 21 июня 2020

Относительно команды в ваш ответ :

sed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t'

Вот несколько примечаний:

Ваш опубликованный образец ввода имеет 1 URL-адрес на строку, поэтому НАЖМИТЕ gm;t в конце вашей команды sed не делает ничего полезного, поэтому либо ваш ввод неадекватен, либо ваш сценарий неверен.

Жестко заданные диапазоны a-z, A-Z и 0-9 включают разные персонажи в разных регионах. Если вы хотели включить все (и только) строчные буквы, прописные буквы и цифры, вам следует заменить a-zA-Z0-9 на класс символов POSIX [:alnum:]. Поэтому либо измените, чтобы использовать класс символов, не зависящий от языкового стандарта, либо укажите нужный языковой стандарт в командной строке, в зависимости от ваших требований, какие символы должны соответствовать в вашем регулярном выражении.

Как и большинство символов, символ + является литерал внутри выражения в квадратных скобках, поэтому его не следует экранировать - замените \+ на +.

Выражение в скобках [^<]? означает «1 или 0 вхождений любого символа, кроме * 1024. * "и аналогично для [^>]?, поэтому, если ваш« url »содержит случайные символы в начале / конце, он будет принят, например:

echo 'xhttp://foo.bar%' | sed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t'
<http://foo.bar%>

I думаю, вы имели в виду используйте <? и >? вместо [^<]? и [^>]?.

Ваше регулярное выражение позволит использовать «url» без букв:

echo 'http://=.9' | gsed -E 's@^[^<]?(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&=]*))[^>]?$@<\1>@gm;t'
<http://=.9>

Если вы отредактируете свой вопрос, чтобы предоставить более действительно репрезентативный ввод образца и ожидаемый результат (включая случаи, когда вы не хотите сопоставить), тогда мы можем помочь вам, НО на основе быстрого поиска в Google того, какой действительный URL-адрес выглядит так, как будто существует несколько l действительные URL-адреса, которые будут запрещены вашим регулярным выражением, и несколько недопустимых, которые будут разрешены, поэтому вы можете спросить об этом в вопросе с тегом url или аналогичным (с тегами, которые у вас есть в настоящее время, мы можем помочь вам реализовать ваше регулярное выражение, но могут быть люди получше, которые помогут с определением вашего регулярного выражения).

1 голос
/ 21 июня 2020

Если входной файл представляет собой просто комментарий, за которым следует список URL-адресов, попробуйте:

sed '1d;s/^[^<]/<&/;s/[^>]$/&>/' websites.txt

Вывод:

<https://www.google.com/>
<https://www.fakesite.co.in>
<https://www.fakesite.co.uk>
<https://www.fakesite.co.uk>
<https://www.google.com/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...