4

Given a string of arbitrary length, a newline and another string of the same length, is it possible to produce regex that will match the character directly below a character on the first line?

For example, what single regex pattern could capture the character below X for all these inputs:

........X..  and  .X.........  and  .....X..... etc.
...........       ...........       ...........

It seems to me, that you must know the position of X in order to get match the character underneath. Manually i can figure out that the pattern

X\.+\n.{8}(.)

that captures the character underneath X in this example

........X..
...........

since i know that X is is the 9th character on the first line. This however doesn't work if X has any other position, which is the core of the problem.

So the question is: Is it possible to create a pattern in regex, that matches the character underneath another character, and what would that look like?

supercigar
  • 43
  • 4
  • 1
    Realize it is a fallacy to think regex can count _dynamically_. Nothing is farther from the truth. –  Aug 15 '19 at 19:23
  • 1
    IMO, this seems too specific for regex and could be done easier leveraging the indexes of the strings. For example, in c# you could find the `index` of your 'X' and then go to the next line, then pull the character that is `strLine[index]` – dvo Aug 15 '19 at 19:25
  • But sure, a regex can be pre-constructed `(?m)^.{15}.+\r?\n^.{15}(.)` where group1 contains said character. –  Aug 15 '19 at 19:25

3 Answers3

5

Assuming you know the length of the first line ahead of time, something like this should work for an X in any position:

/.*?X.{11}(.)/gs

Replace 11 with your desired line length.

https://regex101.com/r/HOA9p1/2/

Joshua Wade
  • 4,755
  • 2
  • 24
  • 44
  • This is really an elegant solution - had totally forgotten about single-line mode! However, it does not work when the line length is unknown, but perhaps then the problem is better solved using something other than regex as @dvo suggests. Thanks for the answers :) – supercigar Aug 15 '19 at 21:28
1

Without knowing the length it's possible by a technique introduced in Vertical Regex Matching.

^(?:.(?=.*\n(\1?.)))*?X.*\n\1?(.)

Here is a demo at regex101

This works in regex flavors supporting forward references like PCRE, .NET, Python, Java (not in JS).
Using possessive \1?+ it will even fail if the offset of X is beyond the end of the line below.

How it works: While the outer (?: non-capturing group ) gets repeated, the capturing group inside a lookahead is growing from itself by adding a character from the consecutive line on each repitition until X will be matched. \1 is a reference to what got captured by the first group from the consecutive line, where it finally gets pasted. The second group shows the character below X.


A variant to replace the character below X with Y by use of another capturing group:
Search for ^((?:.(?=.*\n(\2?.)))*?X.*\n)\2?. and replace with $1$2Y (regex101 demo).

bobble bubble
  • 16,888
  • 3
  • 27
  • 46
0

If you are dealing with your exact example then you basically have to build out all of the combinations as regex does not track the position of a match. If you are using a specific programming language then the language may offer a solution but pure regex does not.

((?:X\.{10}\n)(\.))|((?:\.X\.{9}\n)(:?\.)(\.))|((?:\.{2}X\.{8}\n)(:?\.{2})(\.))

My example only goes up to the third position but you get the idea...

https://regex101.com/r/atVAZK/1/

MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
  • 1
    When dealing with their exact example, the distance between the X on the first line and the intended match on the second line is always the same. Taking this into account hugely simplifies the regex: https://regex101.com/r/HOA9p1/2/ – Joshua Wade Aug 15 '19 at 19:53
  • @JoshuaWade Wow. You should make that into an answer. – MonkeyZeus Aug 15 '19 at 19:55
  • @JoshuaWade - It doesn't work that way https://regex101.com/r/HOA9p1/3, the only thing known is the position of X on the first line of dissimilar lines. –  Aug 15 '19 at 20:15
  • 1
    I suppose you can't make the assumption I made based on the wording. I'm going on their example, where all the line lengths are the same. I think this would only matter if they needed to process multiple examples in one go, but I could be missing something. – Joshua Wade Aug 15 '19 at 20:26