2

I am trying to write a script that performs diff on the output of valgrind using two different executables, but the process ID at the start of each line is littering my diff output. I am trying to remove it using bash commands but can't seem to succeed.

Here's my code so far:

VG_MY=$((valgrind --leak-check=full ./executable < inputfile) 2>&1)
VG_MY=${VG_MY//[0-9]/}

this remove all digits from VG_MY, same as this:

VG_MY="${VG_MY//[[:digit:]]/}"

I've tried to add the == parts in many ways but none worked. Closest I've got is:

VG_MY="${VG_MY//[==[:digit:]==]/}"

Which removes all digits AND '=' from the valgrind output. I need to figure out what I am missing in order to remove only the numbers enclosed by '=' like so: ==123456== from the valgrind output.

EDIT: a sample of valgrind output:

==94953== Memcheck, a memory error detector
==94953== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==94953== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==94953== Command: ./executable
==94953== 
==94953== 
==94953== HEAP SUMMARY:
==94953==     in use at exit: 0 bytes in 0 blocks
==94953==   total heap usage: 13 allocs, 13 frees, 232 bytes allocated
==94953== 
==94953== All heap blocks were freed -- no leaks are possible
==94953== 
==94953== For counts of detected and suppressed errors, rerun with: -v
==94953== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 8 from 6)
7
  • Bash string substitutions are neat, but why do you insist on using them for the purpose? Also, why not pipe the output through tr, sed, awk or any other tool that was created for the task? Since you already use a subshell I don't see why that would be inappropriate. So: $((valgrind --leak-check=full ./executable < inputfile) 2>&1|tr '[:digit:]' '') for example ... May 7 '18 at 13:22
  • 1
    Please show the output of valgrind. Not every one has valgrind installed. May 7 '18 at 13:22
  • 1
    Depending on what your input looks like and what diff you have, you may be able to use the -I option to diff to ignore certain lines completely.
    – Kusalananda
    May 7 '18 at 13:29
  • I just realized that you probably have multiple instances of == PID == in the variable, as valgrind appears to repeat the PID in the output. Sample input & output would be really helpful.
    – Jeff Schaller
    May 7 '18 at 13:33
  • Thanks to you all, I'll add a sample of valgrind output. May 7 '18 at 13:40
7

With ksh or bash -O extglob (or after shopt -s extglob in a bash script) or zsh -o kshglob (or after set -o kshglob in a zsh script):

VG_MY=${VG_MY//+(=)+([0-9])+(=)/}

The +(...) is a ksh extended glob similar to the + extended regexp operator. +(x) matches on one or more xs.

So the above removes all sequences of one or more =s followed by one or more decimal digits followed by one or more =s like sed -E 's/=+[0-9]+=+//g'¹ would.

Not that it would fail to remove 456== inside ==123====456== since the first replacement would remove ==123==== leaving something that doesn't match the pattern. To be able to remove those, you could change it to:

VG_MY=${VG_MY//+(=)[0-9]*([0-9=])=/}

(like sed -E 's/=+[0-9][0-9=]*=//g')

With zsh's own extended globs (zsh -o extendedglob): # is the equivalent of ERE * and ## of ERE + (and (#c1,3) of {1,3}). So, there you can do:

set -o extendedglob
VG_MY=${VG_MY//=##[0-9]##=##/}

¹ Note that while several sed implementations support -E for extended regexps, it's not standard yet, and you can occasionally find some implementations that don't support it. With those, you can skip -E and use \{1,\} as the BRE replacement for + (or use ==* instead of =+).

2
  • Thanks. I tried using the VG_MY=${VG_MY//+(=)+([0-9])+(=)/} code but it didn't work, even when I added "bash -O extglob" to the script file. I am using the .sh extention and execute the script using double click from gnome, I guess I am using bash. May 7 '18 at 13:58
  • 1
    @YekhezkelYovel, you'd need #! /bin/bash - at the start of the script. Better to use the .bash extension if it's a bash script and not a sh script, and use shopt -s extglob within the script to enabled the option. May 7 '18 at 14:08
4

Just delete the ==94953== at the beginning of each line before comparing the outputs:

valgrind --leak-check=full ./executable1 <inputfile 2>&1 | sed 's/^==[0-9]*== //' >output1
valgrind --leak-check=full ./executable2 <inputfile 2>&1 | sed 's/^==[0-9]*== //' >output2

diff -u output1 output2 

Alternatively, which allows you to save the unmodified output and only modify it when running the diff,

valgrind --leak-check=full ./executable1 <inputfile >output1 2>&1
valgrind --leak-check=full ./executable2 <inputfile >output2 2>&1

diff -u <( sed 's/^==[0-9]*== //' <output1 ) <( sed 's/^==[0-9]*== //' <output2 )
4
  • Thanks but I preffer to get the valgrind output as it is and print it to file before I remove the pid. May 7 '18 at 14:44
  • 1
    @YekhezkelYovel See updated answer.
    – Kusalananda
    May 7 '18 at 14:49
  • @YekhezkelYovel: the PID is really pointless information unless you plan on attaching a debugger to the process while it's still running. May 7 '18 at 20:35
  • @0xC0000022L I only need it because my output looks better with it. I know I could work on it to liik better but since there are solutions... May 10 '18 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.