In C++ how do I use regex to replace a string match

In C++11 the regex library was added which allows you to do regex directly:

#include <string>
#include <regex>
...
std::string workingOn("this text string\n");

std::regex expressionStart("^th");
std::string removed = std::regex_replace(workingOn, expressionStart,"");
// removed will contain "is text string"

std::regex expressionReplace("\\bte([^ ]*)");
// match word beginning with 'te' and grab everything to the end of it
// which will be stored in $1 as the first captured match
std::string replaced = std::regex_replace(workingOn, expressionReplace,"ve$1");
// replaced will contain "this vext string"
Advertisements

vim find a line that has this but not that

To find lines which have “This” and “NotThat” it is as simple as:

:g/This\&\(.*NotThat\)\@!

Let’s dive into each piece of this in a little more detail…

The :g is a way to list out all matches in a file. For instance to see all lines listed out which match “This” you could use:

:g/This

Furthermore, if you wanted lines that contained both “This” and “That” then you could use:

:g/This\&\(.*That\)

The reason why the .* is needed is that it looks for the conjoined match (the ampersand) from the previous match. You will notice that the highlighting/match will select the range, i.e.

we use brackets to show the match from [This to That] nothing else matches

By adding the \@! we tell vim to negate that term and viola we are search for “This” and not “That” e.g.

:g/This\&\(.*That\)\@!

Would match the second line, but not the first:

we use brackets to show the match from This to That nothing else matches
on this line we only have This and thus it will match

Notice that only the second line will match.

Using rpm to find an installed program (RedHat, CentOS, Fedora)

To see what programs are installed use:

rpm -qa

If you just installed a program and want to know where it went then grep for it:

$ rpm -qa | grep vim-X11
vim-X11-7.4.160-2.el7.x86_64

Once you have the name of the package, then you can list the files it installed:

$ rpm -ql vim-X11-7.4.160-2.el7.x86_64
/usr/bin/evim
/usr/bin/gex
/usr/bin/gview
/usr/bin/gvim
/usr/bin/gvimdiff
/usr/bin/gvimtutor
/usr/bin/vimx
/usr/share/applications/gvim.desktop
/usr/share/icons/hicolor/16x16/apps/gvim.png
/usr/share/icons/hicolor/32x32/apps/gvim.png
/usr/share/icons/hicolor/48x48/apps/gvim.png
/usr/share/icons/hicolor/64x64/apps/gvim.png
/usr/share/man/man1/evim.1.gz

There is my gvim I was looking for.

P.S. If these newly installed executables aren’t working from PATH, then try opening a fresh shell.

Vim finding and replacing without captures

Normally when doing find and replaces in a file there are some key words that we want to key off, but not replace. This can be a pain because you have to then isolate the part you want to change, capture everything but the changing part, and then reconstruct it in the substitution. Well there is a better way…

If your goal is to prepend all of the name=”bad-.*” with name=”good-.*”, then we would normally have to write something like:

:s/\(name="\)bad\(-.*"\)/\1good\2/g

There is a better way using zoom start ‘\zs’ and zoom end ‘\ze’:

:s/name="\zsbad\ze-/good/g

Happy finding and replacing!

 

Vim Highlighting

I highlight my searches in VIM using the following in my .vimrc:

" Highlight search terms...
set hlsearch
set incsearch " ...dynamically as they are typed.
nmap  n :silent :nohlsearch
" stop highlighting with <leader>n

While demoing or in a code review it is nice to highlight more than one item. You can use searching to match multiple words:

/term1\|term2

Note: You can also us CTRL+R followed by a ‘/’ to paste the exact last search term

However, it is also nice to do highlights in different colors – or to keep a highlight persistent while you search for other terms. To do this I use:

:match Search /pattern/

Now this will use the same highlight color as normal search. You can replace Search, the name of the highlight group, with another group to highlight with a different color (tab completion works here).

To disable the highlighting from match use:

:match none

Enjoy highlighting!

How can I lock and secure (prevent access) to a Windows 10 User Account without deleting it?

We had a user account that we wanted to preserve as a back-up but we also wanted to make sure that if anyone gained access to the machine, that they wouldn’t be able to access the data.

To do this we used the built in Windows 10 Pro encryption in conjunction with disabling the account. This means that they only way to access the data is from the user account, and that account is disabled. Furthermore, if someone copies the files from that user account they won’t be able to read them unless they are on this original computer under the correct account.

To encrypt the files for this User:

  1. Login to the account to lock, select the C:\User\<name> folder
  2. Right-Click and select Properties
  3. In the General tab click on Advanced…
  4. Encrypt contents to secure data
  5. Click on OK
  6. Click on Apply
  7. Select to “Apply to this folder, all subfolders and files” so that all existing files get encrypted (this may take a long time)
    NOTE: If you only select “Apply to this folder” then only new files will be encrypted

To disable the User account:

  1. Logout of that User account
  2. Login to another User account
  3. Run cmd.exe as administrator
  4. For local User:
    net user “User Name” /active:no
    net user “User Name” /active:yes
    For domain User:
    net user “User Name” /active:no /domain

From this point the only way to access that User’s files are from logging in as that User. The User account is disabled and thus gaining access to the data requires special knowledge. Even if you access that User’s files from another account the files will be unreadable – of if you remove the hard drive and copy the files they will be useless.

You might want to back-up the encryption key. We backed up the data on a separate drive which was protected by an air gap, so we did not back-up the key.

If you want to preserve the key then press the Windows Key and type “encrypt” as a search term, you should see the “Manage file encryption certificates”, select that. This wizard will walk you through creating the security key. You should not store this key on this machine as if it is compromised the key to access the data would also be compromised.

 

Searching large source trees in an efficient way on Linux

TL;DR

Here is the alias:

alias search 'find \!:1 -noleaf -type f -not -path "*/boost/*" -not -path "*/extensions/*" -print0 | xargs -0 -n 100 -P 8 grep -I --color -H -n \!:2*'

 

How do I use it?

Here is how I use it:

search [dir] [term] [grep_options]
e.g.
search ./src/ the\ search\ term
search ./src/ keyTerm -A5 -B5

How does it work?

find

This search alias uses find as follows to locate all files under the provided directory (i.e. first argument) while excluding directories that we don’t care about:

find \!:1 -noleaf -type f -not -path "*/boost/*" -not -path "*/extensions/*" -print0

For aliases remember this:

!* is all but the first
!:0 is only the first, the command itself
!:1 is only the first argument
!:2* is all but the first argument
!$ is only the last argument
!:1- is all but the last argument
!! is all
$0 is the shell
$# is the number of args
$$ is the process id (PID)
$! is the PID of the previous command
$? is the return code from the previous command

Thus, the “\!:1” means only the first argument, and the bang (!) has to be escaped.

\!:1

The “-noleaf” is used because I am normally working on Windows/NTFS mounts and it is not safe to assume that directories containing 2 fewer subdirectories than their hard link count only contain files.

-noleaf

We only want to gather files for searching so I use the “-type f”.

-type f

I normally have very large directories which I do not care to search in, so I specify:

-not -path "*/boost/*" -not -path "*/extensions/*"

Finally for the find command I pass “-print0” which returns null (instead of new line) terminated strings. This adds support for paths with spaces in them:

-print0

xargs

The xargs command controls how many files are being passed into grep and it is handling running them in parallel.

xargs -0 -n 100 -P 8 grep -I --color -H -n \!:2*

The “-0” option is used here to tell xargs that the strings coming in are null terminated (this adds support for files with spaces):

-0

The “-n 100” and the “-P 8” options are where the speed and power of this alias come from. The “-n 100” is telling xargs to pass 100 files from find into grep at a time. The “-P 8” is telling xargs to run 8 grep commands in parallel.

This means that if we have a source tree of 1600 files, then grep will be called 16 times and each will be passed 100 files. The best part is that 8 of those grep commands will be running in parallel each on 100 files, so the command finishes as if there were only two (2) grep invocations – very fast even on large source trees:

-n 100 -P 8

grep

The grep command is used to do the actual searching in files.

grep -I --color -H -n \!:2*

The “-I” option ignores binary files:

-I

Colored results make it much easier to see hits:

--color

Because we are passing in the files to grep it may not show the file name where the hit occurred so we add “-H” to print the file name:

-H

The line number is also important, so we add “-n”:

-n

The ability to control grep is handled with an arguments wildcard. Here the “\!:2*” means the second and all subsequent arguments passed into the search alias. Thus the grep search term and all other grep options can be specified after the directory to search:

\!:2*

The final piece is that the xargs command will add the files from the find command to the grep command. It will add 100 (or less if there are less than 100) files to every grep command and each of those will be run in parallel with up to 8 running at any given time.

Enjoy your searching.