0

I've got a text file, containing following lines

<a href="tg://proxy?server=radan.rooznameh.etellaate.rooz.romatism.sbs&port=443&secret=ee32b920dffb51643028e2f6b878d4eac175706c6f6164626f792e636f6d&bot=@mtpro_xyz_bot#ES">1<p> </a>
<a href="tg://proxy?server=digkala-com-heneri-com.1400.melbourne&port=443&secret=ee000000000000000000000000000000006b65746161626f6e6c696e652e636f6d&bot=@mtpro_xyz_bot#IE">2<p> </a>
<a href="tg://proxy?server=103.105.48.76&port=443&secret=eefacacf88a07e73d961d7029c1da7e64b64756f6c696e676f2e636f6d&bot=@mtpro_xyz_bot#GB">3<p> </a>
...
<a href="tg://proxy?server=5.28.193.20&port=443&secret=eed41d8cd98f00b204e9800998ecf8322e7777772e676f6f676c652e636f6d&bot=@mtpro_xyz_bot#DE">1315<p> </a>

I want to replace all ...>1<p>, ...>2<p>, ... near line ends with server addresses.

The text above should become

<a href="tg://proxy?server=radan.rooznameh.etellaate.rooz.romatism.sbs&port=443&secret=ee32b920dffb51643028e2f6b878d4eac175706c6f6164626f792e636f6d&bot=@mtpro_xyz_bot#ES">radan.rooznameh.etellaate.rooz.romatism.sbs<p> </a>
<a href="tg://proxy?server=digkala-com-heneri-com.1400.melbourne&port=443&secret=ee000000000000000000000000000000006b65746161626f6e6c696e652e636f6d&bot=@mtpro_xyz_bot#IE">digkala-com-heneri-com.1400.melbourne<p> </a>
<a href="tg://proxy?server=103.105.48.76&port=443&secret=eefacacf88a07e73d961d7029c1da7e64b64756f6c696e676f2e636f6d&bot=@mtpro_xyz_bot#GB">103.105.48.76<p> </a>
...
<a href="tg://proxy?server=5.28.193.20&port=443&secret=eed41d8cd98f00b204e9800998ecf8322e7777772e676f6f676c652e636f6d&bot=@mtpro_xyz_bot#DE">5.28.193.20<p> </a>

Please, scroll right to see the difference.

In other words, being opened in a browser, this file is rendered as a list of numbers, each of which is a link to the Telegram proxy. I want to replace these numbers with server addresses to make it look more pleasant.

I guess, g command can do the job, however, I don't know how to access matched group or matched pattern.

I've tried many variants, and the best is

:g/server=\(.*\)&/y a|s#>\[0-9\]\+<#\=getreg('a')#

It does not work, because y a command yanks the whole line while I need only part of it. And numbers in subsequent s command are not matched.

Is there any way to do it from the : line, without writing additional functions?

I understand that this task can be easily done with awk + sed, however, I think this is not sportive :)

7
  • Sounds like a sed, grep awk piping problem. Maybe you should ask here: unix.stackexchange.com
    – john-jones
    Feb 14, 2023 at 8:17
  • That's not sportive :)
    – wl2776
    Feb 14, 2023 at 8:20
  • maybe :%!sed ... :)
    – mattb
    Feb 14, 2023 at 8:24
  • Unrelated, but why is there a <p> tag without closing </p> within the <a></a>? This does not look like clean HTML.
    – Friedrich
    Feb 14, 2023 at 8:54
  • @Friedrich, the goal is to quickly find working proxy. I open this file in a browser, then each time I click on lines, browser opens Telegram, and I can check if it works.
    – wl2776
    Feb 14, 2023 at 15:08

3 Answers 3

2

You seem to be confused about :help :global.

The point of :g/<pattern>/<command> is to execute <command> on the lines that match <pattern>, not on the matches themselves.

This means that, in this case, :global is largely unnecessary if you want to use a substitution.

Let's simplify your sample a bit:

<a href="tg://proxy?server=r.r.e.r.r.sbs&p=443&s=c0ffee&b=@mtpro_xyz_bot#ES">1<p> </a>
<a href="tg://proxy?server=d-c-h-c.1.melbourne&p=443&s=c0ffe&b=@mtpro_xyz_bot#IE">2<p> </a>
<a href="tg://proxy?server=103.105.48.76&p=443&s=c0ffee&b=@mtpro_xyz_bot#GB">3<p> </a>

What you want to do can be done with a single substitution:

:%s/\(^.*server=\)\(.\{-}\)\(&.\{-}>\)\d\{-}/\1\2\3\2

The idea is to slice the line into capture groups during the search phase, and reconstruct the line how we want it in the replace phase.

First the slicing:

<a href="tg://proxy?server=r.r.e.r.r.sbs&p=443&s=c0ffee&b=@mtpro_xyz_bot#ES">1<p> </a>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA
                           BBBBBBBBBBBBB
                                                                             C

where A is the part we want to keep as-is, B is the part we want to reuse elsewhere, and C is the part we want to replace with B. What comes after C is irrelevant so we can concentrate on what comes before:

"pattern
\(^.*server=\)\(.\{-}\)\(&.\{-}>\)
+------------+                     group #1
              +-------+            group #2
                       +---------+ group #3

" sample
<a href="tg://proxy?server=r.r.e.r.r.sbs&p=443&s=c0ffee&b=@mtpro_xyz_bot#ES">1<p> </a>
+-------------------------+                                                   group #1
                           +-----------+                                      group #2
                                        +-----------------------------------+ group #3

Now that we have everything that comes before C split in three capture groups, we can reconstruct that part easily:

" replacement
\1\2\3

" result
<a href="tg://proxy?server=r.r.e.r.r.sbs&p=443&s=c0ffee&b=@mtpro_xyz_bot#ES"><p> </a>

and follow up with group #2, which contains the server name:

" replacement
\1\2\3\2

" result
<a href="tg://proxy?server=r.r.e.r.r.sbs&p=443&s=c0ffee&b=@mtpro_xyz_bot#ES">r.r.e.r.r.sbs<p> </a>

There is nothing hard to remember, here:

  • \(...\) creates a capture group,
  • \2 uses capture group #2.
2
  • Thank you for nice explanation. What is {-}? Never seen this before
    – wl2776
    Feb 15, 2023 at 4:06
  • It's a quantifier, meaning "zero or more of the preceding atom, as few as possible". See :help \{-.
    – romainl
    Feb 15, 2023 at 5:35
1

I would do:

%s/proxy?server=\zs\([^&]*\)\(&.*\)\d\ze<p>/\1\2\1/

Here is an explanation:

  • proxy?server=\zs catch the url but ignore the first part for the replacement (\zs)
  • \([^&]*\)catch the server name and store it into \1
  • \(&.*\)\d\ze<p> catch the rest into \2 but exclude <p> from the replacement
  • \1\2\1 do the replacement you want.
1

If sed can do, it :substitute can do it as well (well, mostly).

Using this command: :s/server=\([^&]*\).*>\zs\d\+\ze<p>/\1/

Will convert each of these lines:

<a href="tg://proxy?server=radan.rooznameh.etellaate.rooz.romatism.sbs&port=443&secret=ee32b920dffb51643028e2f6b878d4eac175706c6f6164626f792e636f6d&bot=@mtpro_xyz_bot#ES">1<p> </a>
<a href="tg://proxy?server=digkala-com-heneri-com.1400.melbourne&port=443&secret=ee000000000000000000000000000000006b65746161626f6e6c696e652e636f6d&bot=@mtpro_xyz_bot#IE">2<p> </a>
<a href="tg://proxy?server=103.105.48.76&port=443&secret=eefacacf88a07e73d961d7029c1da7e64b64756f6c696e676f2e636f6d&bot=@mtpro_xyz_bot#GB">3<p> </a>
...
<a href="tg://proxy?server=5.28.193.20&port=443&secret=eed41d8cd98f00b204e9800998ecf8322e7777772e676f6f676c652e636f6d&bot=@mtpro_xyz_bot#DE">1315<p> </a>

into these:

<a href="tg://proxy?server=radan.rooznameh.etellaate.rooz.romatism.sbs&port=443&secret=ee32b920dffb51643028e2f6b878d4eac175706c6f6164626f792e636f6d&bot=@mtpro_xyz_bot#ES">radan.rooznameh.etellaate.rooz.romatism.sbs<p> </a>
<a href="tg://proxy?server=digkala-com-heneri-com.1400.melbourne&port=443&secret=ee000000000000000000000000000000006b65746161626f6e6c696e652e636f6d&bot=@mtpro_xyz_bot#IE">digkala-com-heneri-com.1400.melbourne<p> </a>
<a href="tg://proxy?server=103.105.48.76&port=443&secret=eefacacf88a07e73d961d7029c1da7e64b64756f6c696e676f2e636f6d&bot=@mtpro_xyz_bot#GB">103.105.48.76<p> </a>
...
<a href="tg://proxy?server=5.28.193.20&port=443&secret=eed41d8cd98f00b204e9800998ecf8322e7777772e676f6f676c652e636f6d&bot=@mtpro_xyz_bot#DE">5.28.193.20<p> </a>

Note that this runs on a single line only; use :%s... to run on the whole buffer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.