Parse key value separated by ;

Parse key value separated by ;


Let us use as a sample the following string (the 3 dots mean the same pattern to the infinity):


While doing some code review the previous string was parsed using the split method from String class using the “;” character, after that operation another operation was performed on the token “key=value” string (yes, by the “=” sign) and checking that the key was present with an optional value.

I will not type that code here. The code we are interested here is how to parse this pattern using a unique Regular Expression, in Java that regular expression (and other programming language) is as follows:


That would read (without the back references):

  • Match a word character between one and unlimited times
  • Followed by the “=” character
  • Followed by another word character between zero and unlimited times (optional)
  • This is the interesting part. We will use for this regex a positive lookahead (see my other post related to this topic). This means we are interested to match “;” without making “;” part of the match, it is only there to assert that the match of type “key=value” is true.
  • The last “?” at the end of the regex mean that it is optional, this will help to match a string that does not have a “;” at the end of the string, e.g.


As you can see the implementation is straight, if the string matches each captured token is in the group 2 and 3.

public final class KeyValueParser {

private static final ThreadLocal<Pattern> PATTERN_THREAD_LOCAL = ThreadLocal.withInitial(() -> Pattern.compile("((\\w+)=(\\w*)(?=;)?)"));

 * Example on how to use the PATTERN_THREAD_LOCAL declared above.
 * @param paramsAttrValue a String in the form: key0=value0;key1=value1;key2=value2;keyN=valueN......
 * @return a List with Something key value pair
 public static List<Something> getRequestParams(String paramsAttrValue) {
 List<Something> somethings = new ArrayList<>();
 Matcher regexMatcher = PATTERN_THREAD_LOCAL.get().matcher(paramsAttrValue);
 while (regexMatcher.find()) {
    final String key = 
    final String value =;
    //Do something with key and value
    //Probably Something is a holder for the key and the value.
  return somethings;

 * Forbidden to create instances of this class.
 private KeyValueParser() {
   //Forbidden to create instances of this class.


ThreadLocal for the Pattern seems not needed as Pattern is already thread safe.

Google Parser to (now vCard), version 3.0

Google Parser to (now vCard), version 3.0


I have not dedicated time to the Google Address Book converter, only the Alpine part was done, but today I decided to also include the converter for vCard (v2.1), seems working fine in Mozilla Thunderbird when I import the generated file.

Shortly the code (only of the converter)

package at.mavila.gcontactsalp.converters;

import at.mavila.gcontactsalp.pojos.AddressBook;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

 * Converts the List of Address book to a CharSequence.
 * Created by mavila on 4/16/17.
public class VisitCardConverter implements Converter<List<AddressBook>, CharSequence> {

 private static final Pattern NAME_SPLIT = Pattern.compile("(.+)(\\s+)(.+)");

 public CharSequence convert(final List<AddressBook> addressBooks) {

 if (addressBooks == null || addressBooks.isEmpty()) {
 return StringUtils.EMPTY;

 final StringBuilder stringBuilder = new StringBuilder(); -> addressBook != null).forEach(addressBook -> {



 final AtomicInteger atomicInteger = new AtomicInteger(1);
 addressBook.getAddress().forEach(emailAddress -> stringBuilder.append("email;internet;" + (atomicInteger.getAndIncrement() == 1 ? "HOME:" : "WORK:")).append(emailAddress).append("\r\n"));

 if (!addressBook.getComment().contains("Google")) {


 return stringBuilder.toString();

 private String createN(final String fullName) {

 if (StringUtils.isEmpty(fullName)) {
 return StringUtils.EMPTY;

 final Matcher matcher = NAME_SPLIT.matcher(fullName);

 if (matcher.find()) {
 return + ";" +;

 return fullName+";";


The list of Address book is already parsed by the SAX parser, so we just deal with the conversion in


To call it as a web service:

curl localhost:8080/importVCard -d @mutt.xml --header "Content-Type:text/xml" > vas.vcf

Where mutt.xml is produced by the Google dump command, see my other post related.

Grab the code from:

Finally dual boot in MacBook Pro with Ubuntu Mate

Finally dual boot in MacBook Pro with Ubuntu Mate

Finally I took the decision to install Ubuntu Mate on My MacBook Pro, in general it is not that hard, but it is not trivial as well, briefly the steps I followed:


Install it from Refind. In my case I downloaded the zip file, as of this writing:

I did the installation in “Recovery mode”. Boot the machine and press at the same time CMD+R.

Open a terminal and make the installation of Refind.

On next boot the refind screen should appear.

The following is to install Ubuntu Mate, I got mine in a USB stick and I booted the USB using the EFI boot.

The installation went OK, unfortunately I installed Grub on the same partition as Refind and it didn’t boot anymore, I went into Recovery mode again and reinstalled Refind it, now I have dual boot and Ubuntu Mate works like a charm in my MacBook Pro, well, I had to install the Intel drivers for the graphics card, but I will go into those details in another post.

Regular expressions (positive lookahead and negative lookahead)

Regular expressions (positive lookahead and negative lookahead)

Positive lookahead

“Assert that the regex below can be matched, starting at this position”.

Let’s go with this little example:


This would mean, match a space between one and many times followed by a word character between one and many times only if there is a dot following the previous match:


andy mypass ok orange..see what is going on

The matched text here would be orange (Because there was a dot after “orange”, ah yes, and many spaces before).

Negative lookahead

“Assert that it is impossible to match the regex below starting at this position”.

The regex changes to:

Do you see the difference?. this should read now:

Match a space between one and many times followed by a word character between one and many times only if the following character is not a dot, so what is matched now using our previous.


mypass (Because after "mypass" was a space)
ok (Same reason using the word "ok")
orang (Because after "orang" there is an e)
see (Because after "see" there is a space)

…. and so on

Mac OS X terminal with Gentoo look and feel HOWTO.

Mac OS X terminal with Gentoo look and feel HOWTO.

  • Open a terminal by going to Applications -> Utilities -> Terminal, double click on it, when the prompt appears, type:
vim .profile
  • Type ‘a’ (without the quotes) to start editing and type:
export PS1='\[\033[01;32m\]\u@\h \[\033[01;34m\]\W \$ \[\033[00m\]'
export CLICOLOR=1
export LSCOLORS=ExFxCxDxBxegedabagacad
  • Save the file by typing ESC then ‘w’ and then ‘q’ (no quotes).
  • Close the terminal and restart it again, voila, a Gentoo terminal style in Mac OS X.
How-to Use a Linux Server for Time Machine Backups

How-to Use a Linux Server for Time Machine Backups

Well, this desktop machine is becoming more of a server than anything else, so, I followed this guide to create the backups of my Mac Book Pro using my home network to a 3 TB hard disk attached to the desktop Ubuntu Linux, before setting up the server I created myself a LVM volume following this great guide in the book (see chapter Storage and Management Backup):


Prepare the disk

I created a LVM volume and the final result is:

$ sudo pvdisplay /dev/sdd1
 --- Physical volume ---
 PV Name /dev/sdd1
 VG Name timeMachine
 PV Size 2.73 TiB / not usable 4.42 MiB
 Allocatable yes (but full)
 PE Size 4.00 MiB
 Total PE 715396
 Free PE 0
 Allocated PE 715396
 PV UUID 6pVk0Z-7XhB-SwtB-TYaQ-WG0d-YafZ-rG0uPP


$ sudo vgdisplay timeMachine
 --- Volume group ---
 VG Name timeMachine
 System ID 
 Format lvm2
 Metadata Areas 1
 Metadata Sequence No 2
 VG Access read/write
 VG Status resizable
 Cur LV 1
 Open LV 1
 Max PV 0
 Cur PV 1
 Act PV 1
 VG Size 2.73 TiB
 PE Size 4.00 MiB
 Total PE 715396
 Alloc PE / Size 715396 / 2.73 TiB
 Free PE / Size 0 / 0 
 VG UUID GPj6BC-Zopo-4i3p-jl7t-H1pk-dNtm-hpmqRK

Setting up a server

The next step is to use the following article by Sam Hewitt:

How-to Use a Linux Server for Time Machine Backups

A comment here is that after executing:

cd netatalk-debian

it is necessary to execute first ./configure and then make


After a successful backup I was not able to backup again, Mac showed an error message that the disk was unavailable, for some time my workaround was to restart the server daemon with:

$ sudo systemctl restart netatalk.service

That allowed me to make a new backup again, but restarting the service everytime, seems that for a permanent solution this need to be done in System Preferences


In options select “Share files and folder using AFP”, keep disable the SMB selection if you don’t need to share file with Windows machines.
Now I can just repeat the backup process without restarting the server


Also this file needs to be added:

[mavila@marco-workstation-amd 20:59:26] ~ $ cat /etc/avahi/services/afpd.service

<?xml version="1.0" standalone='no'?><!--*-nxml-*-->

<!DOCTYPE service-group SYSTEM "avahi-service.dtd">


 <name replace-wildcards="yes">%h</name> 

 <service> <type>_afpovertcp._tcp</type> <port>548</port> </service> 

 <service> <type>_device-info._tcp</type> <port>0</port> 




[mavila@marco-workstation-amd 20:59:41] ~ $ 

And it simply works. Nice