0

I am a bit confused by preg_replace as I have not used regex before. I did a bit of searching and couldn't find anything that worked for my situation.

I have logs that contain connections made to the server, like this:

Username connected, address "123.123.123.123:1234"

I want preg_replace to look for this part:

address "123.123.123.123:1234"

And change it to this:

address "snip"

Basically snipping the IP address out, so these logs can be published publicly on the website.

Here's what I currently have that I was testing with.

$new_log = preg_replace('/\address\s"(.*)"/', '', $old_log);

I just need help getting the regex correct.

mario
  • 144,265
  • 20
  • 237
  • 291
userman
  • 23
  • 3
  • 1
    Please show your current code which you have! – Rizier123 Mar 30 '15 at 00:16
  • 1
    My bad! Here's what I currently have that I was testing with. I think it may be a complete failure, this is my first time attempting to use regex ever. (no idea how to use those code tags, this is my first time using stackoverflow ;_;) $new_log = preg_replace('/\address\s"(.*)"/', '', $old_log); – userman Mar 30 '15 at 00:21
  • possible duplicate of [Using a regular expression to validate an email address](http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address) – fuesika Mar 30 '15 at 00:24
  • 1
    This two issues with your regex are: `.*` needs to be made less greedy with an `?`. And the `\a` escaping doesn't belong there. You probably should constrain it somewhat further with `/address\s+"[\d.:]+"/` where `[\d.:]+` matches any combination of numbers, dots, colon. – mario Mar 30 '15 at 00:27
  • 1
    Wow everyone is super useful here! Someone fixed my original post as well. Thank you all so much :) – userman Mar 30 '15 at 00:31

1 Answers1

2

This should work for you:

(Here I get all lines of the file into an array with file(). After this I replace the part address "[ip]" with address "snip" with preg_replace(). At the end I just save the array again in the file with file_put_contents())

<?php

    $lines = file("logs.txt");
    $lines = preg_replace("/\baddress\s?\".*?\"/", "address \"snip\"", $lines);
    file_put_contents("logs.txt", $lines);

?>

regex explanation:

\baddress\s?\".*?\"
  • \b assert position at a word boundary (^\w|\w$|\W\w|\w\W)
    • address matches the characters address literally (case sensitive)
  • \s? match any white space character [\r\n\t\f ]
    • Quantifier: ? Between zero and one time, as many times as possible, giving back as needed [greedy]
  • \" matches the character " literally
  • .*? matches any character (except newline)
    • Quantifier: *? Between zero and unlimited times, as few times as possible, expanding as needed [lazy]
  • \" matches the character " literally

example file before:

Username connected, address "123.123.123.123:1234"
Username connected, address "123.123.123.123:1234"

after:

Username connected, address "snip"
Username connected, address "snip"

Side notes:

Also a few useful links if you want to read more about regex stuff:

Rizier123
  • 58,877
  • 16
  • 101
  • 156
  • Yes! This works perfectly. Do you possible know of any good tutorials to learn regular expression a bit better? – userman Mar 30 '15 at 00:27
  • `array_map` is useless since `preg_replace` can take an array as subject parameter (and obviously returns an array in this case). Why do you use a capture group? There's nothing to capture. Are you sure the second word boundary is needed? Think to the `\K` feature and prefer a greedy negated character class: `[^"]*` to a lazy `.*?`. – Casimir et Hippolyte Mar 30 '15 at 03:25
  • @CasimiretHippolyte Thanks, completely forgot that `preg_replace()` also can take an array. (Don't ask about the second word boundary, don't know what I thought there) – Rizier123 Mar 30 '15 at 12:11
  • I want to use the page to close another but cannot recommend the lazy quantifier. – mickmackusa Sep 17 '21 at 10:14