Я пытаюсь использовать sed для очистки строк URL-адресов, чтобы извлечь только домен.
Так из:
http://www.suepearson.co.uk/product/174/71/3816/
Я хочу:
http://www.suepearson.co.uk/
(с косой чертой или без нее, это не имеет значения)
Я пытался:
sed 's|\(http:\/\/.*?\/\).*|\1|'
и (избегая не жадного квантификатора)
sed 's|\(http:\/\/.*\?\/\).*|\1|'
но я не могу заставить ?
работать не жадный квантификатор ( ), поэтому он всегда совпадает со всей строкой.
sed -E 's...
. Тем не менее, неохотный оператор.cut -d'/' -f1-3
работает просто .Ответы:
Ни базовое, ни расширенное регулярное выражение Posix / GNU не распознает не жадный квантификатор; вам нужно позднее регулярное выражение К счастью, Perl регулярное выражение для этого контекста довольно легко получить:
источник
-pi -e
.perl
это требуется по стандарту POSIXsed
, используя синтаксис, в основном идентичный синтаксисуsed
В этом конкретном случае вы можете выполнить работу без использования не жадных регулярных выражений.
Попробуйте это не жадное регулярное выражение
[^/]*
вместо.*?
:источник
([^&=#]+)=([^&#]*)
. Существуют случаи, которые точно не работают таким образом, например, при разборе URL-адреса для его части хоста и имени пути с окончательной косой чертой, которую необязательно исключать из захвата:^(http:\/\/.+?)/?$
С помощью sed я обычно реализую не жадный поиск, ища что-либо, кроме разделителя до разделителя:
Вывод:
это:
-n
s/<pattern>/<replace>/p
;
разделитель команды поиска вместо того,/
чтобы было проще набиратьs;<pattern>;<replace>;p
\(
...\)
, потом доступны с\1
,\2
...http://
[]
,[ab/]
будет означать либоa
илиb
или/
^
в[]
средствахnot
, поэтому следуют все, кроме вещи в[]
[^/]
значит что угодно, кроме/
персонажа*
повторять предыдущую группу,[^/]*
значит, символы кроме/
.sed -n 's;\(http://[^/]*\)
означает поиск и запоминание,http://
за которым следуют любые символы, кроме как,/
и помните, что вы нашли/
добавьте еще один/
в конце:sed -n 's;\(http://[^/]*\)/'
но мы хотим сопоставить остаток строки после домена, поэтому добавьте.*
\1
), является доменом, поэтому замените сопоставленную строку материалом, сохраненным в группе,\1
и напечатайте:sed -n 's;\(http://[^/]*\)/.*;\1;p'
Если вы хотите включить обратную косую черту и после домена, добавьте еще одну обратную косую черту в группу, чтобы запомнить:
вывод:
источник
sed не поддерживает «не жадный» оператор.
Вы должны использовать оператор «[]», чтобы исключить «/» из совпадения.
PS нет необходимости использовать обратную косую черту "/".
источник
s/([[:digit:]]\.[[1-9]]*)0*/\1/
очевидно, не будет работать хорошо1.20300
. Поскольку первоначальный вопрос касался URL-адресов, их следует указать в принятом ответе.Имитация ленивого (не жадного) квантификатора в
sed
И все другие регулярные выражения!
Нахождение первого вхождения выражения:
POSIX ERE (используя
-r
опцию)Regex:
Sed:
Пример (поиск первой последовательности цифр) Демо :
Как это работает ?
Это регулярное выражение извлекает выгоду из чередования
|
. В каждой позиции движок пытается выбрать самое длинное совпадение (это стандарт POSIX, за которым следуют также несколько других движков), что означает, что оно продолжается.
до тех пор, пока не будет найдено совпадение([0-9]+).*
. Но порядок тоже важен.Поскольку установлен глобальный флаг, движок пытается продолжить сопоставление символ за символом до конца входной строки или нашей цели. Как только первая и единственная группа захвата левой стороны чередования совпадает,
(EXPRESSION)
остаток линии также потребляется немедленно.*
. Теперь мы держим нашу ценность в первой группе захвата.POSIX BRE
Regex:
Sed:
Пример (поиск первой последовательности цифр):
Это похоже на версию ERE, но без чередования. Это все. В каждой позиции двигатель пытается сопоставить цифру.
Если он найден, другие следующие цифры потребляются и захватываются, и остальная часть строки сопоставляется немедленно, в противном случае, так как
*
означает больше или ноль, он пропускает вторую группу захвата\(\([0-9]\{1,\}\).*\)*
и достигает точки,.
чтобы соответствовать одному символу, и этот процесс продолжается.Нахождение первого вхождения с разделителями выражения :
Этот подход будет соответствовать самому первому вхождению строки с разделителями. Мы можем назвать это блоком строк.
Строка ввода:
-EDE:
end
-SDE:
start
Вывод:
Первое регулярное выражение
\(end\).*
сопоставляет и захватывает первый конечный разделительend
и заменяет все совпадения на последние захваченные символы, которые являются конечным разделителем. На этом этапе наш вывод:foobar start block #1 end
.Затем результат передается второму регулярному выражению
\(\(start.*\)*.\)*
, которое совпадает с вышеприведенной версией POSIX BRE. Он соответствует одному символу, если начальный разделительstart
не совпадает, в противном случае он совпадает и захватывает начальный разделитель и соответствует остальным символам.Непосредственно отвечая на ваш вопрос
Используя подход № 2 (выражение с разделителями), вы должны выбрать два подходящих выражения:
EDE:
[^:/]\/
SDE:
http:
Применение:
Вывод:
Примечание: это не будет работать с одинаковыми разделителями.
источник
sed
и во всех других двигателях, следующих тому же стандартному порядку, имеет значение, когда дело доходит до равенства. Такecho 'foo 1' | sed -r 's/.|([0-9]+).*/\1/g'
что нет совпадения, ноecho 'foo 1' | sed -r 's/([0-9]+).*|./\1/g'
есть.Нежадное решение для более чем одного персонажа
Эта ветка действительно старая, но я предполагаю, что людям она все еще нужна. Допустим, вы хотите убить все до самого первого появления
HELLO
. Вы не можете сказать[^HELLO]
...Таким образом, хорошее решение состоит из двух этапов, при условии, что вы можете сэкономить уникальное слово, которое, например, вы не ожидаете при вводе
top_sekrit
.В этом случае мы можем:
Конечно, при более простом вводе вы можете использовать меньшее слово или, возможно, даже один символ.
НТН!
источник
`
я бы использовал<$$>
(поскольку$$
расширяется до идентификатора вашего процесса в оболочке, хотя вам придется использовать двойные кавычки, а не одинарные кавычки, и это может сломать другие части вашего регулярного выражения) или, если доступен Юникод, что-то вроде<∈∋>
.perl
илиpython
вместо или какой - либо другой язык.perl
делает это менее хрупким способом в одной строке ...sed - не жадное совпадение от Christoph Sieghart
Уловка, чтобы получить не жадное соответствие в sed, состоит в том, чтобы сопоставить все символы, кроме того, который заканчивает соответствие. Я знаю, нетрудно, но я потратил драгоценные минуты на это, и сценарии оболочки должны быть, в конце концов, быстрыми и легкими. Так что в случае, если это может понадобиться кому-то другому:
Жадный подход
Не жадное совпадение
источник
Это можно сделать с помощью cut:
источник
Другой способ, не используя регулярное выражение, это использовать метод fields / delimiter, например
источник
sed
конечно есть свое место но это не один из них!Как указал Ди: просто используйте
cut
. В этом случае все гораздо проще и безопаснее. Вот пример, где мы извлекаем различные компоненты из URL, используя синтаксис Bash:дает тебе:
Как видите, это гораздо более гибкий подход.
(все заслуги перед Ди)
источник
источник
sed -E интерпретирует регулярные выражения как расширенные (современные) регулярные выражения
Обновление: -E в MacOS X, -r в GNU sed.
источник
-E
это уникально для BSDsed
и, следовательно, OS X. Ссылки на справочные страницы.-r
действительно приносит расширенные регулярные выражения в GNU,sed
как отмечено в исправлении @ stephancheg. Остерегайтесь при использовании команды известной изменчивости между дистрибутивами 'nix. Я узнал, что трудный путь.-r
Опция GNU sed изменяет только правила экранирования в соответствии сAppendix A Extended regular expressions
информационным файлом и некоторыми быстрыми тестами; фактически он не добавляет не жадный квалификатор (GNU sed version 4.2.1
по крайней мере.)-E
как недокументированный вариант, но в выпуске 4.2.2.177 документация была обновлена, чтобы отразить это, так что в-E
настоящее время это нормально.Все еще есть надежда решить эту проблему с помощью чистого (GNU) sed. Несмотря на то, что это не универсальное решение, в некоторых случаях вы можете использовать «циклы» для удаления всех ненужных частей строки, например:
Единственная проблема здесь заключается в том, что он также обрезает последний символ-разделитель ('/'), но если он вам действительно нужен, вы все равно можете просто вернуть его после окончания цикла, просто добавьте эту дополнительную команду в конце предыдущего командная строка:
источник
Поскольку вы специально указали, что пытаетесь использовать sed (вместо perl, cut и т. Д.), Попробуйте группировать. Это позволяет обойтись без жадного идентификатора, который может быть не распознан. Первая группа - это протокол (т. Е. «Http: //», «https: //», «tcp: //» и т. Д.). Вторая группа - это домен:
Если вы не знакомы с группировкой, начните здесь .
источник
Я понимаю, что это старая запись, но кто-то может найти ее полезной. Поскольку полное доменное имя не должно превышать общую длину 253 символов, замените. * На. \ {1, 255 \}
источник
Это - то, как надежно выполнить не жадное сопоставление многосимвольных строк, используя sed. Допустим , вы хотите изменить каждый ,
foo...bar
чтобы<foo...bar>
так, например , этот вход:должен стать этот вывод:
Для этого вы конвертируете foo и bar в отдельные символы, а затем используете отрицание этих символов между ними:
В приведенном выше:
s/@/@A/g; s/{/@B/g; s/}/@C/g
преобразует{
и}
в строки-заполнители, которые не могут существовать во входных данных, поэтому эти символы затем доступны для преобразованияfoo
иbar
в.s/foo/{/g; s/bar/}/g
преобразуетfoo
иbar
к{
и}
, соответственно ,s/{[^{}]*}/<&>/g
выполняет операцию, которую мы хотим - преобразованиеfoo...bar
в<foo...bar>
s/}/bar/g; s/{/foo/g
преобразует{
и}
обратно кfoo
иbar
.s/@C/}/g; s/@B/{/g; s/@A/@/g
преобразует строки заполнителя обратно в их исходные символы.Обратите внимание, что вышеприведенное не зависит от какой-либо конкретной строки, отсутствующей во входных данных, поскольку она производит такие строки на первом шаге, и не заботится о том, какое вхождение какого-либо конкретного регулярного выражения вы хотите сопоставить, поскольку вы можете использовать
{[^{}]*}
столько раз, сколько необходимо в выражении, чтобы изолировать фактическое совпадение, которое вы хотите, и / или с оператором числового совпадения seds, например, чтобы заменить только второе вхождение:источник
Еще не видели этот ответ, поэтому вот как вы можете сделать это с помощью
vi
илиvim
:Это запускает
vi
:%s
подстановку глобально (завершающийg
), воздерживается от выдачи ошибки, если шаблон не найден (e
), затем сохраняет полученные изменения на диск и завершает работу. Это&>/dev/null
предотвращает кратковременное мигание графического интерфейса на экране, что может раздражать.Мне нравится
vi
иногда использовать для сверхсложных регулярных выражений, потому что (1) perlумер замертво, (2) vim имеет очень продвинутый движок регулярных выражений, и (3) я уже близко знаком сvi
регулярными выражениями в моем повседневном редактировании использования документы.источник
не беспокойтесь, я получил это на другом форуме :)
источник
/home/one/two/three/
если вы добавите еще одно,/
как/home/one/two/three/four/myfile.txt
вы будете жадно совпадатьfour
:,/home/one/two/three/four
вопрос о не жадномsed 's|\(http:\/\/www\.[a-z.0-9]*\/\).*|\1|
тоже работаетисточник
Вот что вы можете сделать с помощью двухэтапного подхода и awk:
Надеюсь, это поможет!
источник
Еще одна версия sed:
Это соответствует
/
сопровождаемый буквенно-цифровым символом (таким образом, не другой слеш), а также остальными символами до конца строки. После этого он заменяет его ничем (т.е. удаляет его).источник
"[[:alnum:]]"
, нет"[:alphanum:]"
.