Строка содержит HTML-тег с суффиксом word + (в данном случае ... rem)

Примере:

<b>SomeText...rem</b>
<u>SomeText...rem</u>
<strong>SomeText...rem</strong>
<a href="/">SomeText...rem</a>
<div>SomeText...rem</div>

Когда слово внутри тега HTML содержит

...rem

Следует удалить весь HTML-тег + слово.

Я могу переименовать "... rem". Это всего лишь маркер.

Это возможно?

2
labu77 6 Фев 2016 в 19:43

2 ответа

Лучший ответ

Я настоятельно рекомендую использовать анализатор HTML за это. Однако, поскольку ваш вопрос требует регулярного выражения, вы можете использовать следующее и заменить совпадения в обратном вызове.

/(?s)<(\w+)[^>]*>(.*?)<\/\1>/

Объяснение:

  • (?s) - флаг s, чтобы символ . также соответствовал символам новой строки.
  • <(\w+)[^>]*> - сопоставить открывающий тег HTML и зафиксировать имя элемента.
  • (.*?) - вторая группа захвата, соответствующая содержимому тега HTML.
  • <\/\1> - сопоставить закрывающий тег HTML с помощью обратной ссылки на основе первой группы захвата (которая является именем тега).

Затем используйте функцию preg_replace_callback, чтобы заменить совпадение пустым жалом, если вторая группа захвата содержит подстроку ...rem. В противном случае ничего не делать, заменяя спичку самой собой.

Живой пример здесь

preg_replace_callback('/(?s)<(\w+)[^>]*>(.*?)<\/\1>/', function ($m) {
  return strpos($m[2], '...rem') !== false ? '' : $m[0];
}, $string);
1
Community 23 Май 2017 в 12:23

Думал сделать снимок.
Вот точный способ сделать это с помощью PHP.

обновить версию

Здесь используется конструкция \K, поэтому нет необходимости в обратной записи
Данные трекера в строку. Просто замените его ничем .
И при этом набирает скорость.

Отформатирован и протестирован:

 # ** Usage **
 # -----------------
 # Find: ''~(?s)(?:(?:(?&Comment)?(?!(?&RawContent)|(?&Comment)).)*\K(?(?=\z)|(?<OpenTag>(?><(?:(?<TagName>[\w:]+)(?:".*?"|\'.*?\'|[^>]*?)+)>)(?<!/>))(?<Body>(?&Char_Not_Tag)*?(?:(?&Tag_Not_TargetOpen)(?&Char_Not_Tag)*?)*?(?=.)(?&RawContent)(?&Char_Not_Tag)*?(?:(?&Tag_Not_TargetOpen)(?&Char_Not_Tag)*?)*?)(?<CloseTag>(?><(?:/\2\s*)>)))|.*?(?:(?&RawContent)|(?&Comment))\K)(?(DEFINE)(?<RawContent>\.\.\.rem)(?<Tag_Not_TargetOpen>(?><(?:(?!\2)[\w:]+(?:".*?"|\'.*?\'|[^>]*?)+)>|(?&Comment)))(?<Char_Not_Tag>(?!(?><(?:[\w:]+(?:".*?"|\'.*?\'|[^>]*?)+)>)|(?&Comment)).)(?<Comment>(?><(?:!(?:(?:DOCTYPE.*?)|(?:\[CDATA\[.*?\]\])|(?:--.*?--)|(?:ATTLIST.*?)|(?:ENTITY.*?)|(?:ELEMENT.*?)))>)))~'
 # Replace: nothing

 # Dot-all modifier
 (?s)

 # Single group, two alternatives.

 (?:
      # Alternative 1 (highest priority)
      # =================================

      # This is the bactracker. This is crucial !
      # We go all the way up until we find
      # the raw content we are looking for,
      # or comments (because they could hide tags).
      # Then we backtrack from there to 
      # find the closest inner open/close tags
      # that contain our content.

      # Tracker1 - Formerly captured, was the replacements
      (?:
           (?&Comment)? 
           (?!
                (?&RawContent) 
             |  (?&Comment) 
           )
           . 
      )*

      # Prevent Tracker1 need to write back
      \K 

      # Conditional Assertion -
      # Have we reached the end of string without 
      # finding the tagged Content ?

      (?(?= \z )
           # ---------------------------------------------
           # Yes -  Don't do anything, the remainder is in
           # Tracker1 and is thrown away.
           # ---------------------------------------------

        |  
           # ---------------------------------------------
           # No - Find the tagged Content.
           # If no match, Tracker1 will backtrack 1 char and retry.
           # Here, Tracker1 will find up to the point
           # of the tagged Content and be consumed, but thrown away.
           # ---------------------------------------------

           # Get Target Open tag
           (?<OpenTag>                         # (1)
                (?>
                     <
                     (?:
                          (?<TagName> [\w:]+ )                # (2), tag name
                          (?: " .*? " | ' .*? ' | [^>]*? )+
                     )
                     >
                )
                (?<! /> )
           )

           # Get Body containing the raw content   
           (?<Body>                            # (3)

                # Stuff before raw content
                (?&Char_Not_Tag)*? 
                (?:
                     (?&Tag_Not_TargetOpen) 
                     (?&Char_Not_Tag)*? 
                )*?

                # The raw content we need
                (?= . )
                (?&RawContent)                       

                # Stuff after raw content
                (?&Char_Not_Tag)*? 
                (?:
                     (?&Tag_Not_TargetOpen) 
                     (?&Char_Not_Tag)*? 
                )*?
           )

           # Get Target Close tag
           (?<CloseTag>                        # (4)
                (?>
                     <
                     (?: / \2 \s* )
                     >
                )
           )
      )
   |  
      # Alternative 2 (lowest priority)
      # =================================

      # Here, we've already backtracked all
      # possibilities from Tracker1.
      # At this point, we have raw content, 
      # or comments that we must get past.
      # Comments because they could hide tags.
      # Just take it off, it will be thrown away.

      # Tracker2 - Formerly captured, was the replacements
      .*? 
      (?:
           (?&RawContent) 
        |  (?&Comment) 
      )

      # Prevent Tracker2 need to write back
      \K 
 )



 # Functions
 # -----------------------
 (?(DEFINE)

      (?<RawContent>                      # (5)

           # Raw content we are looking for.
           # Note - this is content and is not contained
           # in tags nor comments.

           \.\.\.rem                           # '...rem' or whatever
      )

      (?<Tag_Not_TargetOpen>              # (6)

           # Consume any tag that
           # is not the target Open tag.
           # Comsume comment as well.
           (?>
                <
                (?:
                     (?! \2 )
                     [\w:]+ 
                     (?: " .*? " | ' .*? ' | [^>]*? )+
                )
                >
             |  
                (?&Comment) 
           )
      )

      (?<Char_Not_Tag>                    # (7)

           # Consume any charater
           # that does not begin a tag or comment
           (?!
                (?>
                     <
                     (?:
                          [\w:]+ 
                          (?: " .*? " | ' .*? ' | [^>]*? )+
                     )
                     >
                )
             |  
                (?&Comment) 
           )
           .  
      )

      (?<Comment>                         # (8)

           # Comment
           (?>
                <
                (?:
                     !
                     (?:
                          (?: DOCTYPE .*? )
                       |  (?: \[CDATA\[ .*? \]\] )
                       |  (?: -- .*? -- )
                       |  (?: ATTLIST .*? )
                       |  (?: ENTITY .*? )
                       |  (?: ELEMENT .*? )
                     )
                )
                >
           )
      )
 )

Контрольный пример

Вход:

<div>blah blah <i>some text</i> ...rem</div>
<b>SomeText...rem</b>
<u>SomeText...rem</b>
<strong>SomeText...rem</b>
<a href="/">SomeText...rem</a>
<div>SomeText...rem</div>

Выход:

 **  Grp 0                      -  ( pos 0 , len 44 ) 
<div>blah blah <i>some text</i> ...rem</div>  
 **  Grp 1 [OpenTag]            -  ( pos 0 , len 5 ) 
<div>  
 **  Grp 2 [TagName]            -  ( pos 1 , len 3 ) 
div  
 **  Grp 3 [Body]               -  ( pos 5 , len 33 ) 
blah blah <i>some text</i> ...rem  
 **  Grp 4 [CloseTag]           -  ( pos 38 , len 6 ) 
</div>  

---------------------

 **  Grp 0                      -  ( pos 46 , len 21 ) 
<b>SomeText...rem</b>  
 **  Grp 1 [OpenTag]            -  ( pos 46 , len 3 ) 
<b>  
 **  Grp 2 [TagName]            -  ( pos 47 , len 1 ) 
b  
 **  Grp 3 [Body]               -  ( pos 49 , len 14 ) 
SomeText...rem  
 **  Grp 4 [CloseTag]           -  ( pos 63 , len 4 ) 
</b>  

---------------------

 **  Grp 0                      -  ( pos 86 , len 0 )  EMPTY 
 **  Grp 1 [OpenTag]            -  NULL 
 **  Grp 2 [TagName]            -  ( pos 70 , len 1 ) 
u  
 **  Grp 3 [Body]               -  NULL 
 **  Grp 4 [CloseTag]           -  NULL 

---------------------

 **  Grp 0                      -  ( pos 114 , len 0 )  EMPTY 
 **  Grp 1 [OpenTag]            -  NULL 
 **  Grp 2 [TagName]            -  ( pos 93 , len 6 ) 
strong  
 **  Grp 3 [Body]               -  NULL 
 **  Grp 4 [CloseTag]           -  NULL 

---------------------

 **  Grp 0                      -  ( pos 120 , len 30 ) 
<a href="/">SomeText...rem</a>  
 **  Grp 1 [OpenTag]            -  ( pos 120 , len 12 ) 
<a href="/">  
 **  Grp 2 [TagName]            -  ( pos 121 , len 1 ) 
a  
 **  Grp 3 [Body]               -  ( pos 132 , len 14 ) 
SomeText...rem  
 **  Grp 4 [CloseTag]           -  ( pos 146 , len 4 ) 
</a>  

---------------------

 **  Grp 0                      -  ( pos 152 , len 25 ) 
<div>SomeText...rem</div>  
 **  Grp 1 [OpenTag]            -  ( pos 152 , len 5 ) 
<div>  
 **  Grp 2 [TagName]            -  ( pos 153 , len 3 ) 
div  
 **  Grp 3 [Body]               -  ( pos 157 , len 14 ) 
SomeText...rem  
 **  Grp 4 [CloseTag]           -  ( pos 171 , len 6 ) 
</div>  

Предыдущая версия с трекером напишите обратно.

 # ** Usage **
 # -----------------
 # Find: '~(?s)(?:(?<Tracker1>(?:(?&Comment)?(?!(?&RawContent)|(?&Comment)).)*)(?(?=\z)|(?<OpenTag>(?><(?:(?<TagName>[\w:]+)(?:".*?"|\'.*?\'|[^>]*?)+)>)(?<!/>))(?<Body>(?&Char_Not_Tag)*?(?:(?&Tag_Not_TargetOpen)(?&Char_Not_Tag)*?)*?(?=.)(?&RawContent)(?&Char_Not_Tag)*?(?:(?&Tag_Not_TargetOpen)(?&Char_Not_Tag)*?)*?)(?<CloseTag>(?><(?:/\3\s*)>)))|(?<Tracker2>.*?(?:(?&RawContent)|(?&Comment))))(?(DEFINE)(?<RawContent>\.\.\.rem)(?<Tag_Not_TargetOpen>(?><(?:(?!\3)[\w:]+(?:".*?"|\'.*?\'|[^>]*?)+)>|(?&Comment)))(?<Char_Not_Tag>(?!(?><(?:[\w:]+(?:".*?"|\'.*?\'|[^>]*?)+)>)|(?&Comment)).)(?<Comment>(?><(?:!(?:(?:DOCTYPE.*?)|(?:\[CDATA\[.*?\]\])|(?:--.*?--)|(?:ATTLIST.*?)|(?:ENTITY.*?)|(?:ELEMENT.*?)))>)))~'
 # Replace: '$1$6'
0
9 Фев 2016 в 08:21