2015-05-22 4 views
1

Я использую follwing линии для производства части списка HTML:СЭД: выполнить замену в спине ссылки

sed -r 's|(.*dn=([^&]+).*)|<li><a href="\1">\2</a></li>|' file.txt 

И я хотел бы выполнить несколько замен, но только на \2 обратной ссылки, не всей линии. Это возможно, и как?

+0

Я так не считаю. Используйте 'perl', чтобы вы могли получить обратную ссылку в переменной и обработать ее перед заменой. – Barmar

+0

Но, может быть, если вы покажете примеры того, что вы хотите сделать, есть способ, уточняя регулярное выражение, чтобы получить части '\ 2' в разные обратные ссылки. – Barmar

+0

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

ответ

3

С SED это можно сделать так:

sed -r 'h; s|(.*dn=([^&]+).*)|<li><a href="\1">\n</a></li>|; x; s//\2/; s/foo/bar/; G; s/(.*)\n(.*)\n(.*)/\2\1\3/' filename 

То есть:

#!/bin/sed -rf 

h             # copy line to hold buffer 

s|(.*dn=([^&]+).*)|<li><a href="\1">\n</a></li>| # generate the outer parts of 
                # the wanted result, with a 
                # newline where \2 will go 
                # when it was edited 

x             # exchange hold buffer and 
                # pattern space to bring back 
                # the input line 

s//\2/           # isolate \2 (// reattempts the 
                # previous regex) 

s/foo/bar/          # your substitutions here 

G             # append hold buffer to pattern 
                # space 

s/(.*)\n(.*)\n(.*)/\2\1\3/      # rearrange the parts in the 
                # desired order. 

Учитывая на вход

http://www.example.com/website.html?a=b&dn=foo&asd=fgh 

это произведет

<li><a href="http://www.example.com/website.html?a=b&dn=foo&asd=fgh">bar</a></li> 

Side Примечание: Так как ваш \1 является весь матч, было бы, возможно, будет лучше использовать & в замене первого s команды, т.е.

#        v-- here 
s|.*dn=([^&]+).*|<li><a href="&">\n</a></li>| 

Это потребует s//\1/ вместо s//\2 в решение выше, так как группа захвата теперь \1.

+0

's // Использование \ 1 /' будет использовать тот же шаблон поиска, что и предыдущий, поэтому он будет идти в среднем вопросе ** НО ** существует замена между двумя так '\ 1', а затем - не обязательно тот же (или соответствующий шаблон вообще), потому что он не принимает результат «s1». – NeronLeVelu

+0

@NeronLeVelu Исходный текст возвращается к пространству шаблона перед второй заменой, поэтому те же самые вещи будут захвачены во второй раз, когда применяется регулярное выражение. – Wintermute

+0

'echo" hello "| sed 's/\ (. \) \ 1/o /; s // [&]/'' return 'he [oo]' не 'he [ll] o' или' heo [ll] o'. второй 's' использует тот же шаблон, но с новым контентом – NeronLeVelu

-1

Использование @ вход Wintermute в образце:

http://www.example.com/website.html?a=b&dn=foo&asd=fgh 

и GNU AWK для 3-арг, чтобы соответствовать(), чтобы держать группы захвата в массиве:

$ awk 'match($0,/(.*dn=([^&]+).*)/,a) { $0="<li><a href=\"" a[1] "\">" a[2] "</a></li>"} 1' file 
<li><a href="http://www.example.com/website.html?a=b&dn=foo&asd=fgh">foo</a></li> 

$ awk 'match($0,/(.*dn=([^&]+).*)/,a) { sub(/foo/,"bar",a[2]); $0="<li><a href=\"" a[1] "\">" a[2] "</a></li>"} 1' file 
<li><a href="http://www.example.com/website.html?a=b&dn=foo&asd=fgh">bar</a></li> 

Просто заменить sub(/foo/,"bar",a[2]) с тем, что она вы действительно хотите сделать со второй группой захвата.