Jump to content

Recommended Posts

Hello. Lets find some random string that I need to replace, ex. # ab . cd $. And I want to change # to 3 and $ to 4 only if it is in this form of string. I write rexexp pattern:

 

'/#(.*)(.)(.*)($)/'

 

and replacement:

 

3

 

but why the whole string is replaced to 3, not only #? How can I change my string to 3 ab . cd $?

Hey. I need to replace one particular sign only if it is part of specified string. In this case it is:

 

# ab . cd $

 

where ab, cd are any random string, and there is dot which divides them. So if I had a string # abcd, without dot and $, it should not change. But if it is like

 

# ab . cd $

 

# changes into 3. This what I got was changing the whole string to 3, but I need 3 ab . cd $ - how can I do it?

:psychic: You really need to show the code you are using to do the replacement. I suspect it is the replacement part that you have not coded correctly.

 

By the way, I am not an expert at regular expressions, but that regexp will match your example string, it will also match stuff that does not fit your stated requirements.

 

'/#(.*)(.)(.*)($)/'

 

says:

  • string starts with a literal "#"
  • any number of any character (including NO characters at all)
  • any single character
  • any number of any character (including NO characters at all)
  • a literal "$"

 

I would think something like this would do it:

 

'/#(.+\..+$)/'

Thanks for all the answers. The code I am using is:

<?php
$patterns = array('/(?<!e)abcd/');
$replacements = array('abcde');
$string=$_POST['link'];
echo preg_replace($patterns, $replacements, $string);
?>

and when I have negation on the beginning of the string, it is good, becaise when I have string ex. habcd, it changes to habcde, and h is remaining. But if I place it on the end of the string, ex. abcd(?<!e), string like abcdh changes to abcde, while I need abcdeh (h not disappearing). I hope that it will be more clear now.

 

What is ~ and ? for in this code?

$string = preg_replace('~#(.*?\..*?\$)~', '3\1', $string);

 

and what is for + here?

'/#(.+\..+$)/'

Is it always special? Or only when it is at the end of the expression? I started to escape it, which would not hurt if it didn't need it, but then I didn't.

 

Yes, it is a special character, regardless of where it is in the pattern..it's just that you usually only see it at the end of the pattern because usually it doesn't make sense to use it elsewhere.  But it also comes up a lot if you are combining it with alternations, or with multi-line mode.  Only place that it is treated literally is inside a character class.

 

http://www.php.net/manual/en/regexp.reference.meta.php

I don't see any relationship between that pattern: '/(?<!e)abcd/' and your original post. Maybe we need to talk about what you are trying to do. Moving the negative look-behind to the end: abcd(?<!e) does not seem right. They way I read that, it says "find the letters 'abc' followed immediately by a 'd' that does not have an 'e' before it -- well, the pattern says to find 'abcd' so there is no way that an 'e' will be before the 'd'. -- I may be way off here, the assertions still confuse me a bit. I'm going to defer to the RegExperts here, cause I am really out of my depth.

 

What is ~ and ? for in this code?

$string = preg_replace('~#(.*?\..*?\$)~', '3\1', $string);

 

The '~' is just the delimiter used for the expression. Your examples use a slash ('/'). Pretty much any character can be used. I personally usually use a tilde ('~') since I rarely will be searching for them.

The '?' makes the '*' "less greedy" so it will not eat up the period ('.') that follows. A '.*' will match anything, and regexp's usually try to find the longest possible match, using the '?' says to find the shortest possible match considering the next character in the expression to be found.

 

The '+' says to find one or more of the preceding character (in this case a '.' which says ANY character). Using '.*' will match zero or more characters.

 

 

@Crayon Violent - O.K. thanks. I will make note of that and always escape the '$' inside an expression. I really need to study the assertions and alternations more.

I don't see any relationship between that pattern: '/(?<!e)abcd/' and your original post. Maybe we need to talk about what you are trying to do. Moving the negative look-behind to the end: abcd(?<!e) does not seem right. They way I read that, it says "find the letters 'abc' followed immediately by a 'd' that does not have an 'e' before it -- well, the pattern says to find 'abcd' so there is no way that an 'e' will be before the 'd'. -- I may be way off here, the assertions still confuse me a bit. I'm going to defer to the RegExperts here, cause I am really out of my depth.

Thanks for the name "negative lookbehind". I concluded that in this case it must be something like "look forward", I found "look ahead" and it is much more clear now. I am going to try to do this and I will ask if I get problems. Thank you very much. All that I needed was "positive lookahead". The code that worked for me was:

 

'/\#(?=.*?\..*?$)/'

Lookbehind has to have a fixed length pattern to match, so you cannot use quantifiers in a lookbehind. 

 

Example:

 

abc is a fixed length; it has exactly 3 characters.

 

.* is not a fixed length, because it can be 0 or more characters.

 

As DavidAM mentioned... your followup posted code and what you are saying doesn't match what it is you previously said... so as I said in the beginning, you need to try harder to be a lot more clear in what you are trying to do.  Give several examples of real input and what you want the results to look like.

 

 

Okay, sorry. I want to change every string like: # ab . cd $ to 3 ab . cd 4, example lets find some random strings:

 

# 123 . abc $

# 456 . asd $

# 147 . qwe $

# 123 . zxc $

123 #

 

and I want to change #->3 and $->4 only in strings which are this form. String 123 # shouldn't be changed. The result should be:

 

3 123 . abc 4

3 456 . asd 4

3 147 . qwe 4

3 123 . zxc 4

123 #

 

I solved problem #->3 with positive lookahead, and if positive lookbehind could be various length, it would be solved also for $->4. Any other ideas?

Thanks for answer and help. I'm sorry, but I cant understand what more could I explain, may I ask for asking more specific question?

 

I think you are missing the point... unless there's other stuff you aren't mentioning, the lookahead/behind assertions are overkill, not necessary.  Does the code I just posted work for you?

 

What is ${1} for? Is it repetition of the same element?

 

$1 is the first captured group in the pattern.  ${1} is the same thing, but the {..} specifically tells php to look at $1 because you want to use that "4" afterwards, so it's there to keep it from being confused and try to use $14 (the 14th captured group - which doesn't exist).

quickly and helpful answer, thanks :) this is the only thing which I need to do, and this grouping looks nice. It works for me. I am a bit unexperienced in regexp, and I can do many unnecessary things. I liked these forums. You are really helpful. It was all what I needed, and there is no other point what I am missing :)

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.