简体   繁体   中英

A PHP Regex for list Items and line breaks

I need a Regex to search for "item one" and get "Amet Elit" . Or "Title" and get "One sentence with\\na linebreak!"

- item one: Amet Elit
- Title: One sentence with 
a line break!
- Desc: Hello and thank you for your help!

So the Regex has to find everything after - , some specific words and a : . And this string ends before a line break with a following - .

I tried this

/[^-\s'item one']:*(.*)/g

under https://regex101.com/ .

You can try with this pattern:

/^- ([^:]*): (.*(?>\R.*)*?(?=\R- |\R*\z))/m

demo

The key and the value are captured in group 1 and group 2. The group 2 contains a non-greedy quantifier to match until the condition in the lookahead succeeds. The lookahead (?=...) checks if the second group is followed by a newline ( \\R ) or the end of the string ( \\z )

To obtain a specific item, replace ([^:]*) with whatever you want.

You can use this search function:

function srch($input, $key) {
    preg_match('/(?<=\b' . preg_quote($key, '/') . ': ).*?(?=\n-|$)/s', $input, $m);
    return $m[0];
}

Then call it as:

$input = "- item one: Amet Elit
- Title: One sentence with
a line break!
- Desc: Hello and thank you for your help!";

php> echo srch($input, 'Title')
One sentence with
a line break!

php> echo srch($input, 'item one')
Amet Elit

php> echo srch($input, 'Desc')
Hello and thank you for your help!

Code Demo

The following should work:

^-\h*([^:\R]*)\h*:\h*(.*$(?:\R[^-].*$)*)

Fiddle .

Broken up in parts:

  • ^-\\h*([^:\\R]*)\\h* : matches the words between the starting hyphen (must occur at line start) up to a colon, trimmed ( \\h* are horizontal blanks outside the capture). There cannot be line-breaks in that part ( \\R )

  • \\h*(.*) : matches the rest of the line (left-trimmed).

  • (?:\\R[^-].*$)* : non-capturing ( (?: ) group allowing zero or more lines following, on the condition they do not start with a hyphen ( \\R[^-] ).

In PHP:

$input = "- item one: Amet Elit
- Title: One sentence with 
a line break!
- Desc: Hello and thank you for your help!";

preg_match_all("#^-\s*([^:\R]*)\s*:\s*(.*(?:\R[^-].*$)*)#m",
               $input, $matches);

foreach ($matches[1] as $i => $prefix) {
    echo $prefix . " | " . $matches[2][$i] . "<br>";
}

Output:

item one | Amet Elit

Title | One sentence with

a line break!

Desc | Hello and thank you for your help!

Use positive lookbehind:

(?<=^- item one: ).*$

If the phrase ( item one in the above example) is not constant, you could use \\K to drop everything matched so far to achieve a positive lookbehind with variable length:

^- [^:]*: \K.*$

Here is a slight alternation to allow you to match over multiple lines. Don't forget the gm flags

^- [^:]*: \K(.|\n)*?(?=^-|$)

See it in action

You're not far off.

Instead of matching exactly with item one you want to match with a word or space, so that would be [\\w\\s]*

Something along the lines of ^- [\\w\\s]*: (.*) should work, though you haven't mentioned how this information is coming in. One line, are you trying to search and replace? using preg_match ?

Check this link out to see it working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM