Invert regexreplace result?

Please check the FAQ (https://www.xyplorer.com/faq.php) before posting a question...
Post Reply
highend
Posts: 13346
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Invert regexreplace result?

Post by highend »

Hi,

I have a text file that is filled with a ffmpeg output of a simple

Code: Select all

ffmpeg.exe -i somevideofile 2>file.txt
Many lines but I'm only interested in the resolution of the video file.

A few lines to demonstrate it:

Code: Select all

      title           : 01:32:04.269
    Chapter #0.11: start 5911.447000, end 5911.447000
    Metadata:
      title           : 01:38:31.447
    Stream #0.0(ger): Video: h264 (High), yuv420p, 1280x528 [PAR 1:1 DAR 80:33], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
    Stream #0.1(ger): Audio: dca (DTS), 48000 Hz, 5.1, s16, 1536 kb/s (default)
    Stream #0.2(eng): Audio: dca (DTS), 48000 Hz, 5.1, s16, 1536 kb/s
At least one output file must be specified
The interesting part is the 1280x528.

It isn't hard to find via a regexp:

Code: Select all

\d+x\d+
but the problem is, how do I throw anything else away in a regexreplace() command?

Ofc I could do it with e.g. grep from the unixtools collection but I'd like use only internal xyplorer script function in this case.
One of my scripts helped you out? Please donate via Paypal

Stefan
Posts: 1360
Joined: 18 Nov 2008 21:47
Location: Europe

Re: Invert regexreplace result?

Post by Stefan »

What do you mean by "anything else"?
All the other lines? Or the uninterested parts of the line with the resolution?

You can do both:

Code: Select all

$str = "<clipboard>";

  foreach($line, $str, "<crlf>"){
    $match = regexreplace($line, ".+ (\d+[x|X]\d+) .+", "$1");
    if ($match != $line) {msg "$line <crlf 3>$match";}
  }
Result:

Code: Select all

    Stream #0.0(ger): Video: h264 (High), yuv420p, 1280x528 [PAR 1:1 DAR 80:33], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)

1280x528
The trick is that regexreplace() returns the original input if the regex didn't match.
If the regex didn't match, because the pattern is not found, we get the original input back as result.
If the pattern match, we get the result of the regex evaluation back.
So, if we get the original input back, we know the regex didn't have matched and we can skip this line.
If the result is not ( != ) the original input, the pattern has matched somehow.
If the pattern or the result is the right thing we want or not is an other story :wink:

To extract the resolution inside the line we use an back reference group
by putting the regex to extract the need part "\d+[x|X]\d+" into parentheses (\d+[x|X]\d+)
which we can access/reuse by "$1"

The part before and after we match by the regex ".+ " and " .+"
but without backreference group parentheses, because we only have to match them, but didn't need them in the result.

Backreference group parentheses are counted from left to right.
So f.ex. we could also smtg like
regexreplace($line, "(.+ )(\d+[x|X]\d+)( .+)", "$2");

then we would get:
$1 -> " Stream #0.0(ger): Video: h264 (High), yuv420p, "
$2 -> "1280x528"
$3 -> " [PAR 1:1 DAR 80:33], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)"


HTH? :D
Last edited by Stefan on 02 Sep 2011 23:56, edited 1 time in total.

highend
Posts: 13346
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Invert regexreplace result?

Post by highend »

"Anything else" was: throw away anything that is not the match itself, regardless if it's on the same line or any other.

A clever solution, Stefan!

Mine is a bit more complicated and uses grep *g* but I'll diss that one now...

In a further step I take the result, split it in two variables, do a $result = $firstvalue / $secondvalue; and use this value for the ffmpeg command (-aspect $result) to produce an accurate output.

As always, thanks a lot :)
One of my scripts helped you out? Please donate via Paypal

Stefan
Posts: 1360
Joined: 18 Nov 2008 21:47
Location: Europe

Re: Invert regexreplace result?

Post by Stefan »

highend wrote:In a further step I take the result, split it in two variables,

Code: Select all

$firstvalue  = regexreplace($line, ".+ (\d+)[x|X](\d+) .+", "$1");
$secondvalue = regexreplace($line, ".+ (\d+)[x|X](\d+) .+", "$2");

highend
Posts: 13346
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Invert regexreplace result?

Post by highend »

My way was:

Code: Select all

$firstvalue = gettoken($match, 1, "x");
$secondvalue = gettoken($match, 2, "x");
Don't know which solution is faster though :)

This is now a short part of the script:

Code: Select all

	$FFmpegLog = readfile($FFmpegLogFile);

	foreach($Line, $FFmpegLog, "<crlf>"){
		$VideoResolution = regexreplace($Line, ".+ (\d+[x|X]\d+) .+", "$1");
		if($VideoResolution != $Line) { break; }
	}
	
	// Check if $VideoResolution contains a valid value
	$ValidationCheck = strpos("$VideoResolution", "x");
	end ($ValidationCheck == "-1"), "No valid video resolution found, aborted!";

	$FirstValue = gettoken($VideoResolution, 1, "x");
	$SecondValue = gettoken($VideoResolution, 2, "x");

	// Trim the result after two decimals
	$AspectRatio = substr(($FirstValue / $SecondValue), 0, 4);
	echo $AspectRatio;
For 1280x528 it returns e.g. 2.42
One of my scripts helped you out? Please donate via Paypal

Post Reply