6

Need regular expression to parse a log line, I have to select data after 10th occurrences of pipe symbol |

Sample log line;

Info     device  Allow:FWD|TCP|data1|data2|data3|data4|data5|data6|data7|data8|data9|data10|data11|0|1|0|0|0|0||||||

I have to select data9 from above log line.

Below is the expression I am using right now, this is for a Java program

Expresssion:

\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|

selection group 11

Instead of escape character one by one would like to skip/ignore 10 pipe symbols and select data9

  • 14
    Now you have two problems. – Mark Mar 31 at 21:10
  • 3
    Why do you need a regular expression to do this? – curiousdannii Apr 1 at 14:56
  • In the regex posted "selection group 11" is actually data10, not data9. (However, it won't actually match at all since you are matching 1 too many pipe symbols, or there is a pipe symbol missing from the "sample log line"?) – MrWhite Apr 1 at 23:12
30

That's why quantifiers are for.

^(?:[^|]*\|){10}([^|]*)
| improve this answer | |
  • 1
    ^(?:.*?\|){10}(.*?)\| This is cleaner in my view. The questioner says they're using Java and Java totally supports this syntax. – Olivier Grégoire Apr 1 at 11:10
  • 9
    @OlivierGrégoire: Your regex takes 117 steps, mine 37 steps – Toto Apr 1 at 12:06
  • Wow, first time I hear about "steps". I gotta check that metrics in the future. I still find my regex more "clean", but I totally agree yours might be more efficient. – Olivier Grégoire Apr 1 at 12:18
  • 2
    [^|]* is definitely faster, because there's no possibility of backtracking. I might even use [^|\n] in order to ensure the regex doesn't run off the end of a line (e.g. in case a line has less than 10 fields for any reason). – nneonneo Apr 1 at 19:38
  • 1
    @OlivierGrégoire Yours looks for at least 10 | characters. Toto's looks for exactly 10. – CJ Dennis Apr 2 at 1:22
21

If you're using a regex in the context of another programming language (Python, C#, etc.), that language likely has some type of string splitting function. In my experience, it's usually easier to split on the delimiter and get a list/array of values instead of using regexes to split.

| improve this answer | |
  • This is only true of a very simple single character split. The moment you need to do "beginning of the string" or "this character or that character" or "replace with this pattern that is matched" then you get a nightmare with nested array looping logic. – Nelson Apr 1 at 3:37
  • 7
    C# for example both has parameter in split str.Split(new []{'|'}, 10) (alternatively "|".ToCharArray()), and indexing with str.Split('|')[10..] if you want the remainder split too. These solutions will often run faster than a regex, so for simple cases where they can be used it might be a better choice. If course if you need complexity then regex can be better, but for this case split functions may be better suited. – Tedd Hansen Apr 1 at 10:22
  • 2
    @Nelson "This is only true of a very simple single character split." - Like the example given in the question. – MrWhite Apr 1 at 22:24
  • In my experience, text parsing always has edge cases that wasn't initially thought of. You don't want to pick a solution where solving edge cases becomes exponentially more difficult. – Nelson Apr 2 at 2:45
  • In C# there is an overload where a string can be passed as a delimiter, not only a single char: docs.microsoft.com/en-us/dotnet/api/… – Marian Spanik Apr 2 at 11:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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