1

I'm trying to replace the first "|" but by starting by the end of the string:

usr/bin/pipe|pipe|name|28|-rwxr-xr-x|root:root||46711b361edd4512814d9b367ae765f42a71d729708b3f2e162acb8f64592610|

my file name is pipe|pipe|name and i want my regex to return me usr/bin/pipe|pipe|name

I've begin by this regex: .([^\|]*)$ but I don't know how to go further in the pipes : https://regex101.com/r/ttbiab/3

And in Java:

String strLine = "usr/bin/pipe|pipe|name|28|-rwxr-xr-x|root:root||46711b361edd4512814d9b367ae765f42a71d729708b3f2e162acb8f64592610|";
strLine = strLine.replaceAll(".([^\\|]*)$", "[:124:]");
System.out.println("strLine : " + strLine);
TheSmartMonkey
  • 857
  • 1
  • 7
  • 23

3 Answers3

0

You can try something like this [\|]([^\|]*[\|]){5}$. It matches the pipe count of 5 followed by first pipe from the ends.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Akshay Mishra
  • 189
  • 1
  • 8
0

If there is a fixed number of 6 pipes until the end of the string, and you want to select the individual pipes before that to replace them, you could make use of \G to assert the position at the previous match and use a lookahead to assert that what is on the right is 6 times not a pipe followed by a pipe.

(?:([^\|]*)|\G(?!^))\|([^|]*)(?=(?:[^|]*\|){6})

In Java:

String regex = "(?:([^\\|]*)|\\G(?!^))\\|([^|]*)(?=(?:[^|]*\\|){6})";
  • (?: Non capturing group
    • ([^\|]*) Capture in group 1 matching not a pipe 0+ times using a negated character class
    • | OR
    • \G(?!^) Assert position at the end of the previous match, not at the start
  • ) Close non capturing group
  • \|([^|]*) Match a pipe and capture in group 2 match 0+ times not a pipe
  • (?= Non capturing group
    • (?:[^|]*\|){6} Positive lookahead, assert what is on the right is 6 times not a pipe followed by a pipe
  • ) Close non capturing group

Regex demo | Java demo

If you want to replace the pipe with for example #, then use the 2 capturing groups:

$1#$2
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
0

Based on your comments, it looks like you don't know how many pipes will be in the filename, but you do know how many pipes are in the input string that aren't in the filename. In this case, regex may not be the best approach. There are a couple of different ways to do this, but perhaps one of the easiest to understand and maintain would be to split the String, and then recombine it with replacements where applicable:

String input = "usr/bin/pipe|pipe|name|28|-rwxr-xr-x|root:root||46711b361edd4512814d9b367ae765f42a71d729708b3f2e162acb8f64592610|";
String pipeReplacement = ":124:";
int numberOfPipesToKeep = 7;

String[] split = input.split("\\|");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
    sb.append(split[i]);
    if (i < split.length - numberOfPipesToKeep) {
        sb.append(pipeReplacement);
    } else {
        sb.append("|");
    }
}

String output = sb.toString();
System.out.println(output);

The above sample handles any number of pipes, is pretty configurable, and is (in my opinion) a lot easier to understand and debug than trying to use regular expressions.

Jordan
  • 2,273
  • 9
  • 16