3

I'm trying to change all slashes on a line to replace with the 3-characters block at the beginninig of each line. (PMC,PAJ, etc in below example)

.PMC.89569XX/90051XX/90204XX/89533XX/90554XX/90053XX/90215XX/89874XX/89974XX/90481XX/90221XX/90508XX/90183XX/88526XX/89843XX/88041XX/90446XX/88515XX/89574XX/89847XX/88616XX/90513XX/90015XX/90334XX/89649XX.T00
.PAJ.77998XX/77896XX.T00 .PAG.78116XX/78104XX/77682XX/07616XX/77663XX/77863XX/07634XX/78088XX/77746XX/78148XX.T00 .PKC.22762XX/22358XX/22055XX/22672XX/22684XX/22154XX/22608XX/22768XX/22632XX/22266XX/22714XX/22658XX/22631XX/22288XX/22020XX/22735XX/22269XX/22138XX/22331XX/22387XX/22070XX/22636XX/22629XX/22487XX/22725XX.T00

The desired outcome should be:

PMC.89569XXPMC90051XXPMC90204XXPMC89533XXPMC90554XXPMC90053XXPMC90215XXPMC89874XXPMC89974XXPMC90481XXPMC90221XXPMC90508XXPMC90183XXPMC88526XXPMC89843XXPMC88041XXPMC90446XXPMC88515XXPMC89574XXPMC89847XXPMC88616XXPMC90513XXPMC90015XXPMC90334XXPMC89649XX.T00

I'm not sure how to accomplish this. This is what I have so far:

 (.)([A-Z]{3})(.)(\/)
QAZ001
  • 109
  • 7

2 Answers2

5

If you only plan to support ECMAScript 2018 and newer, you may achieve what you need with a single regex:

.replace(/(?<=^\.([^.]+)\..*?)\//g, "$1")

See the regex demo.

Details

  • (?<=^\.([^.]+)\..*?) - a positive lookbehind that, immediately to left of the current location, requires
    • ^ - start of string
    • \. - a dot
    • ([^.]+) - Group 1: one or more chars other than a dot
    • \. - a dot
    • .*? - any 0+ chars, other than linebreak chars, as few as possible
  • \/ - a / char.

JS demo:

var strs = ['.PMC.89569XX/90051XX/90204XX/89533XX/90554XX/90053XX/90215XX/89874XX/89974XX/90481XX/90221XX/90508XX/90183XX/88526XX/89843XX/88041XX/90446XX/88515XX/89574XX/89847XX/88616XX/90513XX/90015XX/90334XX/89649XX.T00','.PAJ.77998XX/77896XX.T00','.PAG.78116XX/78104XX/77682XX/07616XX/77663XX/77863XX/07634XX/78088XX/77746XX/78148XX.T00','.PKC.22762XX/22358XX/22055XX/22672XX/22684XX/22154XX/22608XX/22768XX/22632XX/22266XX/22714XX/22658XX/22631XX/22288XX/22020XX/22735XX/22269XX/22138XX/22331XX/22387XX/22070XX/22636XX/22629XX/22487XX/22725XX.T00'];
for (var s of strs) {
 console.log(s.replace(/(?<=^\.([^.]+)\..*?)\//g, "$1"));
}
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks Wiktor, this almost does the trick. Except it only works for the first line. 'PMC' not for the others at the same time 'PAJ' etc – QAZ001 Dec 23 '18 at 21:10
  • @QAZ001 If you have to run it for a multiline string, use `m` modifier: `s.replace(/(?<=^\.([^.\n]+)\..*?)\//gm`. If there are any glitches, use `/(?<=(?:^|\n)\.([^.]+)\..*?)\//g` – Wiktor Stribiżew Dec 23 '18 at 21:25
  • See https://regex101.com/r/VB232V/2, `(?:^|\n)` works better than the `^` with `m` modifier in this case. – Wiktor Stribiżew Dec 23 '18 at 21:31
  • Almost but still contains flaws. İt works fine upto PAJ. But than it starts to change PAG and PKC into PAJ's. – QAZ001 Dec 24 '18 at 04:24
  • @QAZ001 It [actually works](https://regex101.com/r/VB232V/3), there is a problem with line breaks in your string. Just find them out and add to the `(?:^|[\n\r])` pattern. – Wiktor Stribiżew Dec 25 '18 at 01:41
1

I am not sure if you can do it with just one regex and you will have to probably do it as a two step process. First, you can capture the three capital letters using substring() method and then you can replace all slashes with those three letter appearing in the beginning of character after first dot. Here is a demo with JS code,

function transformLine(s) {
    var repStr = s.substring(1,4);
    var replacedStr = s.replace(/\//g, repStr);

    return replacedStr.substring(1,replacedStr.length);
}

var lines = [".PMC.89569XX/90051XX/90204XX/89533XX/90554XX/90053XX/90215XX/89874XX/89974XX/90481XX/90221XX/90508XX/90183XX/88526XX/89843XX/88041XX/90446XX/88515XX/89574XX/89847XX/88616XX/90513XX/90015XX/90334XX/89649XX.T00", ".PAJ.77998XX/77896XX.T00", ".PAG.78116XX/78104XX/77682XX/07616XX/77663XX/77863XX/07634XX/78088XX/77746XX/78148XX.T00", ".PKC.22762XX/22358XX/22055XX/22672XX/22684XX/22154XX/22608XX/22768XX/22632XX/22266XX/22714XX/22658XX/22631XX/22288XX/22020XX/22735XX/22269XX/22138XX/22331XX/22387XX/22070XX/22636XX/22629XX/22487XX/22725XX.T00"];

for (var i = 0;i<lines.length;i++) {
    console.log("Before: " + lines[i]);
    console.log("After: " + transformLine(lines[i])+"\n\n");
}

I've replaced the first dot as your expected output does not have it.

Let me know if this works for you.

Edit:

I have updated the code to provide a function that takes a string as input and returns the modified string. Please check the demo.

Edit2: Solving it mostly using regex

This one liner in the function does all the job for you in transforming your line to the required one.

function transformLine(s) {
    return s.replace(/\//g, /^.(.{3})/.exec(s)[1]).replace(/^./,'');
}

var lines = [".PMC.89569XX/90051XX/90204XX/89533XX/90554XX/90053XX/90215XX/89874XX/89974XX/90481XX/90221XX/90508XX/90183XX/88526XX/89843XX/88041XX/90446XX/88515XX/89574XX/89847XX/88616XX/90513XX/90015XX/90334XX/89649XX.T00", ".PAJ.77998XX/77896XX.T00", ".PAG.78116XX/78104XX/77682XX/07616XX/77663XX/77863XX/07634XX/78088XX/77746XX/78148XX.T00", ".PKC.22762XX/22358XX/22055XX/22672XX/22684XX/22154XX/22608XX/22768XX/22632XX/22266XX/22714XX/22658XX/22631XX/22288XX/22020XX/22735XX/22269XX/22138XX/22331XX/22387XX/22070XX/22636XX/22629XX/22487XX/22725XX.T00"];

for (var i = 0;i<lines.length;i++) {
    console.log("Before: " + lines[i]);
    console.log("After: " + transformLine(lines[i])+"\n\n");
}

As you can see here, this line,

return s.replace(/\//g, /^.(.{3})/.exec(s)[1]).replace(/^./,'');

does all the job you need. It first extracts the three capital letter using this /^.(.{3})/.exec(s)[1] then all slashes are replaced with this captured word and then finally first character which is a dot is removed using this /^./,'' and finally returns the string you need.

Let me know if this is what you wanted. Else let me know if you further wanted it in any particular way.

Pushpesh Kumar Rajwanshi
  • 18,127
  • 2
  • 19
  • 36